javascript - React - 有人可以做到这一点吗?

标签 javascript reactjs

所以我在 Codepen 上发现了一位名叫 Sean 的绅士完成的漂亮布局,他使用 React 创建了这个水平 Accordion 。

代码如下但 here如果您需要 fork 的话,就是 Codepen。

所以,我遇到的问题是;如何能够在每个“类别”中使用不同的“项目”。现在所有“类别”都使用相同的“项目”。我相信这很简单,我不理解,但我就是找不到它。

class ProjectList extends React.Component {
createProjectListItem(project) {
    let byline = project.acf.project_byline
    let client = project.acf.project_client
    return (
        <li key={'project-' + project.id}>
            <a to={'/projects/' + project.slug}>
              <h3 className="projectlist--client">{client}</h3>
              <h4 className="projectlist--byline">{byline}</h4>
            </a>
        </li>
    );
}
render() {
    return (
        <div className="project-list">
            <ul className="menu vertical">
              { this.props.projects.map( this.createProjectListItem ) }
            </ul>
        </div>
    )
    }
}

class ProjectCategory extends React.Component {
    constructor(props) {
        super(props)

        this.setActive = this.setActive.bind(this)

        this.state = {
          projects: []
        }
    }
    componentWillMount() {
      // this.getProjects(); // Codepen switched to HTTPS, so I have to load JSON manually instead of the json-generator
      this.setState({
        projects: [{"acf":{"project_byline":"ut ullamco sunt","project_credits":[{"credit_role":"ut","credit_name":"Leann"},{"credit_role":"aliquip","credit_name":"Hernandez"},{"credit_role":"consequat","credit_name":"Ashlee"}],"project_description":"Enim est qui Lorem officia adipisicing irure minim. Eu enim fugiat cupidatat elit anim pariatur irure quis aute velit enim. Adipisicing consequat sunt eiusmod reprehenderit nisi fugiat esse ut. Consequat ea ad deserunt mollit quis labore Lorem do qui officia labore. Incididunt reprehenderit anim sunt velit sunt est sit anim.","project_client":"pariatur","project_thumbnail":"https://unsplash.it/1000/1000","project_category":"aute"},"tags":["incididunt"],"categories":[2],"excerpt":{"rendered":"Eiusmod reprehenderit incididunt aute do commodo sint laboris exercitation Lorem excepteur sit cillum aute irure."},"content":{"rendered":"Enim id ex excepteur incididunt in deserunt mollit eiusmod adipisicing officia quis aliquip. Qui aute et consequat consectetur aute consectetur laborum. Non non sint reprehenderit velit proident aliqua elit eiusmod laboris veniam elit ea. Incididunt excepteur et esse minim amet in magna ea enim."},"title":{"rendered":"non"},"link":"https://seanma.de","guid":"7d115e77-9566-4389-b544-deffaf76d058","slug":"proident","id":"58653533ca121cbaf664b199"},{"acf":{"project_byline":"consectetur aute aliquip","project_credits":[{"credit_role":"dolor","credit_name":"Hampton"},{"credit_role":"mollit","credit_name":"Kate"},{"credit_role":"consectetur","credit_name":"Riddle"}],"project_description":"Reprehenderit in mollit fugiat cupidatat consectetur minim Lorem eiusmod commodo laboris dolor minim tempor eiusmod. Et aute et exercitation dolore fugiat pariatur in ipsum anim dolor qui laborum laborum. Elit qui ad ea exercitation laboris sunt ut et est sunt duis. Esse duis ad ipsum aliqua nulla enim minim minim. Ullamco do tempor ex magna et ipsum sint et voluptate cupidatat anim labore esse.","project_client":"et","project_thumbnail":"https://unsplash.it/1000/1001","project_category":"nisi"},"tags":["et"],"categories":[8],"excerpt":{"rendered":"Ipsum excepteur laboris nostrud sit proident."},"content":{"rendered":"Anim non Lorem id fugiat. Do cillum qui veniam qui ad mollit pariatur Lorem. Lorem veniam nulla commodo aliqua. Fugiat laboris cillum excepteur tempor aliqua sit exercitation sit labore nostrud et."},"title":{"rendered":"in"},"link":"http://seanma.de","guid":"444da15a-5160-48bb-bf6f-7d820d1f62e8","slug":"dolor","id":"58653533702dae7921a80c46"},{"acf":{"project_byline":"eiusmod ullamco commodo","project_credits":[{"credit_role":"nulla","credit_name":"Dickson"},{"credit_role":"esse","credit_name":"Trevino"},{"credit_role":"aliquip","credit_name":"Joni"}],"project_description":"Ullamco minim occaecat officia anim laborum laboris velit cupidatat esse aliqua irure exercitation. Occaecat elit labore est exercitation aute qui voluptate adipisicing consectetur officia. Adipisicing tempor tempor culpa enim cupidatat.","project_client":"magna","project_thumbnail":"https://unsplash.it/1000/1002","project_category":"consectetur"},"tags":["incididunt"],"categories":[3],"excerpt":{"rendered":"Tempor quis cupidatat elit quis aute velit amet pariatur cupidatat ullamco voluptate."},"content":{"rendered":"Elit commodo aliqua do occaecat consectetur sint ex. Eiusmod proident eiusmod ullamco occaecat cillum voluptate duis. Tempor enim ullamco duis sint est. Minim voluptate sint nisi enim ut pariatur officia cillum excepteur sint aliquip. Amet in proident dolor amet incididunt laborum sint commodo cillum officia consectetur proident aliqua. Incididunt nostrud nulla mollit adipisicing adipisicing nulla exercitation."},"title":{"rendered":"tempor"},"link":"http://seanma.de","guid":"75909710-4410-4b59-bec8-f5cbb342471a","slug":"ullamco","id":"58653533e961f59631955144"},{"acf":{"project_byline":"culpa tempor commodo","project_credits":[{"credit_role":"eiusmod","credit_name":"Pennington"},{"credit_role":"fugiat","credit_name":"Jocelyn"},{"credit_role":"enim","credit_name":"Byrd"}],"project_description":"Cupidatat incididunt laborum cillum ea dolore quis. Exercitation Lorem eu ad ex. Laboris ipsum excepteur sunt eu irure ipsum. Consequat cupidatat sunt Lorem proident nostrud velit voluptate nulla quis cillum fugiat. Mollit fugiat nulla enim irure commodo officia nulla minim incididunt labore. Labore cillum irure Lorem ut laborum ad laborum.","project_client":"sint","project_thumbnail":"https://unsplash.it/1000/1003","project_category":"do"},"tags":["adipisicing"],"categories":[7],"excerpt":{"rendered":"Nostrud laborum aliquip enim aute aute tempor."},"content":{"rendered":"Consectetur fugiat commodo aliquip culpa occaecat anim cupidatat adipisicing cupidatat voluptate reprehenderit incididunt. Irure consequat enim deserunt incididunt dolor nisi id do cupidatat in Lorem. Laborum amet id minim enim. Nulla sint enim commodo ut qui duis reprehenderit Lorem nulla. Ad sint aliquip aute Lorem ut reprehenderit duis dolore occaecat non. Elit deserunt amet laborum non labore est deserunt eiusmod."},"title":{"rendered":"nulla"},"link":"http://seanma.de","guid":"9581e2ce-8146-4cf5-8d0b-9107ab850828","slug":"non","id":"58653533c66184064ccedc40"},{"acf":{"project_byline":"ex deserunt est","project_credits":[{"credit_role":"non","credit_name":"Hutchinson"},{"credit_role":"quis","credit_name":"Donaldson"},{"credit_role":"aliqua","credit_name":"Marcie"}],"project_description":"Eu ullamco anim adipisicing duis adipisicing sint sit incididunt pariatur sit. Non veniam deserunt nulla aute. Eiusmod minim ut Lorem consequat. Ut ad ad qui do aute. Duis ipsum do consequat exercitation nisi anim id laboris fugiat dolore ex ut consectetur excepteur. Esse deserunt nostrud esse consectetur pariatur mollit. Enim proident enim non occaecat eu sint nostrud.","project_client":"occaecat","project_thumbnail":"https://unsplash.it/1000/1004","project_category":"sit"},"tags":["aliqua"],"categories":[3],"excerpt":{"rendered":"Esse commodo amet excepteur ex ad."},"content":{"rendered":"Commodo ad et veniam sunt non pariatur elit ex anim esse consequat veniam. Ad magna nulla ea anim est in nostrud magna magna proident voluptate officia. Irure nisi do adipisicing nostrud mollit est non duis quis nisi amet veniam Lorem proident."},"title":{"rendered":"mollit"},"link":"http://seanma.de","guid":"472ababf-2340-4301-b63d-9bec9640a19e","slug":"incididunt","id":"586535332e3781792a099619"}]
      })
    }
    getProjects() {
      let _this = this
      let catid = this.props.cat.id
      let url = 'http://beta.json-generator.com/api/json/get/EyrhxmRVz'
      fetch(url).then( response => response.json() )
      .then( json => { _this.setState({ projects: json }) })
    }
    getBackground(i){
      let _this = this

      // let bgArray = this.state.projects.map(function(project){
      //   return project.acf.project_thumbnail
      // });

      let bg = this.props.cat.thumbnail

      return bg
    }
    setActive() {
        this.props.handleClick(this.props.Index)
    }
    getWidth(isActive) {
        let w = 'calc(20vw - 20px)'
        if (isActive) { w = '500px' }
        return w
    }
    render() {
      // console.log(this.state.projects) 
        let name = this.props.cat.name
        let thumbnail = this.getBackground()

        let { active, focused, shiftLeft, isLast } = this.props

        let styles = {
          container: {
            transform: (function() {
                return (active)
                    ? 'scale(1.1) translate3d(0, 0, 0)'
                    : 'scale(1) translate3d(0, 0, 0)'
            })()
          }, item: {
              transform: (function() {
                  let direction = (shiftLeft) ? '-': ''
                  let transform = 'translate3d(0, 0, 0)'
                  if (focused) {
                    if (!active) {
                      transform = 'translate3d('+ direction +'100%, 0, 0)'
                    }
                  }
                  return transform
              })()
          }, background: {
              background: 'url(' + thumbnail + ') no-repeat center center',
              backgroundSize: 'cover',
              height: '500px',
              width: (this.getWidth(active))
          }
        }
        let classes = classNames({category: true, isActive: active, isLast, shiftLeft})
        return (
            <li className={classes} style={styles.item}>
                <div className="category--content">
                    <h2>{name}</h2>
                    <ProjectList projects={this.state.projects}/>
                </div>
                <div className="category--image-container" onClick={this.setActive} style={styles.container}>
                    <div className="category--image" style={styles.background}></div>
                </div>
                <div className="category--name">
                  <h6>{name}</h6>
                </div>
                <div className="category--closeButton">
                  <a href="#">Back</a>
                </div>
            </li>
        )
    }
}

class Collection extends React.Component {

    constructor(props) {
        super(props);

        this._handleClick = this._handleClick.bind(this)
        this.categoryNode = this.categoryNode.bind(this)
        this._focusOff = this._focusOff.bind(this)

        this.state = {
          open: false,
          activeIndex: null,
          categories: []
        }
    }
    componentDidMount() {
      // this._getCategories(); // Codepen switched to HTTPS, so I have to load JSON manually instead of the json-generator
      this.setState({
        categories: [{"thumbnail":"https://unsplash.it/1200/1200","link":"http://seanma.de","taxonomy":"category","count":6,"name":"consequat","slug":"commodo","id":"586537da62981d5fb8c21617"},{"thumbnail":"https://unsplash.it/1200/1201","link":"http://seanma.de","taxonomy":"category","count":8,"name":"non","slug":"laborum","id":"586537da60c040bc1e3060a1"},{"thumbnail":"https://unsplash.it/1200/1202","link":"http://seanma.de","taxonomy":"category","count":3,"name":"non","slug":"commodo","id":"586537daffc67c66ec4dc356"},{"thumbnail":"https://unsplash.it/1200/1203","link":"http://seanma.de","taxonomy":"category","count":6,"name":"velit","slug":"voluptate","id":"586537dae1be34396786ce5f"},{"thumbnail":"https://unsplash.it/1200/1204","link":"http://seanma.de","taxonomy":"category","count":2,"name":"non","slug":"voluptate","id":"586537dab274a22da2f3edae"}]
      })
    }
    _getCategories() {
      let _this = this
      let url = 'http://beta.json-generator.com/api/json/get/E1NpHQAEf';
      fetch(url).then( response => response.json() )
      .then( json => { _this.setState({ categories: json }) })
    }
    _handleClick(i){
      this.setState({
        activeIndex: i,
        open: true
      })
    }
    _focusOff(e){
      e.preventDefault()
      if (e.target.className !== 'category--image') {
        this.setState({
          activeIndex: null,
          open: false
        })
      }
    }
    categoryNode(cat, i){
        let isLast = ( i === this.state.categories.length - 1 || i === this.state.categories.length - 2)
        let shiftLeft = ( i < this.state.activeIndex )

        return (
          <ProjectCategory
            cat={cat}
            key={'cat-' + i}
            handleClick={this._handleClick}
            active={i === this.state.activeIndex}
            focusOff={this._focusOff}
            focused={this.state.open}
            shiftLeft={shiftLeft}
            Index={i}
            isLast={isLast}
          />
        )
    }
    render() {
      let catNodes = this.state.categories.map(this.categoryNode)
      let classes = classNames({
        focused: this.state.open
      })
      return (
        <div className={'categories--menu-container ' + classes} onClick={this._focusOff} style={{height: window.innerHeight}}>
          <ul className="categories menu">
            {catNodes}
          </ul>
        </div>
      )
    }
}

class App extends React.Component{
  render(){
    return(
      <div className="App">
        <Collection/>
      </div>
    )
  }
}
ReactDOM.render(<App />, document.querySelector("#root"))
html, body {
  background-color: #222;
  width: 100%;
  height: 100%;
  overflow: hidden;
}

a, h1, h2, h3, h4, h5, h6 {
  color: white;
}

a:hover, a:hover > * {
  color: grey;
}

.categories--menu-container {
  position: relative;
  height: 100%;
  height: calc(100vh - 150px);
  width: 100%;
}

ul.categories {
  position: absolute;
  top: 50%;
  left: 50%;
  -webkit-transform: translate(-50%, -50%);
          transform: translate(-50%, -50%);
}

.category {
  position: relative;
}

/*content*/
.category--content {
  position: absolute;
  top: 50px;
  white-space: nowrap;
  right: 0;
  -webkit-transform: translateX(100%);
          transform: translateX(100%);
}

.category--content h2 {
  text-align: left;
  font-size: 44px;
  -webkit-transform: translateX(-50px);
          transform: translateX(-50px);
  text-transform: uppercase;
  font-weight: bold;
}

.category--content .project-list {
  padding: 0 0 0 30px;
}

.category--content,
.category--content .project-list,
.category--content .project-list li {
  text-align: left;
}

.category--name {
  position: absolute;
  white-space: nowrap;
  width: calc(100% - 5px);
  -webkit-transition: all 0.5s ease;
  transition: all 0.5s ease;
  padding-top: 5px;
  margin-top: 15px;
  margin-right: 5px;
  border-top: 1px solid #666;
  color: #666;
}

.category--name h6 {
  font-size: 16px;
  color: inherit;
  text-transform: capitalize;
}

.focused .category--name {
  opacity: 0;
}

.projectlist--client {
  font-size: 18px;
  margin-bottom: 0px;
  -webkit-text-stroke: 0;
  text-transform: capitalize;
  font-weight: bold;
}

.projectlist--byline {
  font-size: 12px;
  font-family: 'Nothing You Could Do', sans-serif;
}

/*last item content*/
.isLast .category--content {
  right: initial;
  left: 0;
  -webkit-transform: translateX(-100%);
          transform: translateX(-100%);
}

.isLast .category--content h2 {
  -webkit-transform: translateX(50px);
          transform: translateX(50px);
  text-align: right;
}

.isLast .category--content .project-list {
  padding: 0 30px 0 0;
}

.isLast .category--content,
.isLast .category--content .project-list,
.isLast .category--content .project-list li {
  text-align: right;
}

/*inactive states*/
li.category {
  -webkit-transition: -webkit-transform 500ms ease;
  transition: -webkit-transform 500ms ease;
  transition: transform 500ms ease;
  transition: transform 500ms ease, -webkit-transform 500ms ease;
  position: relative;
  z-index: 1;
}

.category--content {
  text-align: right;
  z-index: -1;
  visibility: hidden;
  pointer-events: none;
}

.category--content .project-list li {
  opacity: 0;
  -webkit-transition: all 300ms ease;
  transition: all 300ms ease;
}

.category--image-container {
  background: #222;
  -webkit-transition: all 500ms ease;
  transition: all 500ms ease;
}

/*active states*/
li.category.isActive {
  z-index: 99;
}

.isActive .category--content {
  z-index: 99;
  visibility: visible;
  pointer-events: all;
}

.isActive .category--content .project-list li {
  opacity: 1;
}

/*image states*/
.category--image:hover, .category--image:focus, .focused .category--image:hover, .focused .category--image:focus {
  opacity: 1;
  cursor: pointer;
}

.category--image {
  opacity: 0.7;
  -webkit-transition: opacity 500ms ease, width 500ms ease 100ms;
  transition: opacity 500ms ease, width 500ms ease 100ms;
}

.focused .category--image {
  opacity: 0.25;
}

.focused .isActive .category--image {
  opacity: 0.75;
}

.category--closeButton {
  opacity: 0;
  text-align: center;
  position: absolute;
  width: 100%;
  bottom: -5rem;
  -webkit-transition: opacity 200ms ease;
  transition: opacity 200ms ease;
}

.focused .isActive .category--closeButton {
  opacity: 1;
  z-index: 99;
}

.category--closeButton a {
  margin: -15px;
  padding: 15px;
}

/*hover state*/
.category--image {
  /*transition: width 500ms ease;*/
}

.categories--menu-container:not(.focused) li.category:hover .category--name {
  border-color: #eee;
  color: #eee;
}

/*Nav*/
.right-arrow {
  position: fixed;
  bottom: 50px;
  right: 50px;
  display: inline-block;
}

.left-arrow {
  position: fixed;
  bottom: 50px;
  left: 50px;
  display: inline-block;
}

.left-arrow a, .right-arrow a {
  background-color: #222;
  z-index: 9;
  position: relative;
  padding: 5px;
  font-size: 12px;
}

.right-arrow img, .left-arrow img {
  position: absolute;
  top: 50%;
  left: 50%;
  -webkit-transform: translate(-50%, -45%);
          transform: translate(-50%, -45%);
  z-index: 0;
  width: 140px;
  max-width: none;
}

.left-arrow img {
  -webkit-transform: translate(-50%, -50%) scaleX(-1);
          transform: translate(-50%, -50%) scaleX(-1);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<link href="https://cdn.jsdelivr.net/foundation/6.2.0/foundation.min.css" rel="stylesheet">
<link href="https://raw.githubusercontent.com/necolas/normalize.css/master/normalize.css" rel="stylesheet">
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.2/react.js"></script>
<script type="text/javascript" src="https://codepen.io/nevernotsean/pen/68c150995678a82a39e33f71ef5ce683"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.2/react-dom.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/classnames/2.2.5/index.min.js"></script>
<script type="text/javascript" src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/152635/codepen-ga.js"></script>
<div id="root"></div>

最佳答案

JSX (JavaScript XML) 无法直接在浏览器中运行。您需要将 JSX 文件转换为纯 JavaScript 才能在浏览器中运行。使用BabelJS为了这。

关于javascript - React - 有人可以做到这一点吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45645743/

相关文章:

javascript - 值(value)观问题 Formik

javascript - Angular 2 ajax加载并执行脚本标签

javascript - 使用 fetch 方法读取 RapidAPI JSON 响应

javascript - 停止 Google Maps API v3 中的空闲事件

javascript - 按钮点击计数器

javascript - 使用 material-ui 时出现 proptypes 错误

javascript - 在 React 中将字符串下载为 .txt 文件

javascript - 谷歌地图标记窗口自定义设计

javascript - React Router 无法渲染路由

ReactJS - 组件未将 this.state.object 正确传递给另一个组件