使用React.js在选项卡上切换类别

9

我有一个包含3个选项卡的tab-component:

React.DOM.ul( className: 'nav navbar-nav', 
    MenuItem( uid: 'home')
    MenuItem( uid: 'about')
    MenuItem( uid: 'contact)
)

MenuItem.render中:

React.DOM.li( id : @props.uid, className: @activeClass, onClick: @handleClick,
    React.DOM.a( href: "#"+@props.uid, @props.uid)
)

每次我点击一个项目,都会调用一个backbone路由器,然后调用“tab-component”,接着调用“page-component”。
我仍在努力理解这种基本上是单向数据流的事实。而且我习惯直接操作DOM。
我想做的是,将“.active”类添加到所点击的选项卡,并确保它从非活动选项卡中删除。
我知道CSS技巧,可以使用“data-”属性,并对为“true”或“false”的属性应用不同的样式。
backbone路由器已经获得了变量“uid”,并调用了正确的页面。我只是不确定如何最好地在选项卡之间切换类,因为同一时间只能有一个选项卡处于活动状态。
现在,我可以保留一些记录,以确定哪个选项卡被选择和已选择,并进行切换等操作。但React.js已经具有此记录功能。
您看到的“@handleClick”,我甚至不想使用,因为路由器应该告诉“tab-component”哪个选项卡应该给出“className:'.active'”。而且我想避免使用jQuery,因为React.js不需要直接操作DOM。
我已经尝试过一些@state的方法,但我知道肯定有一种非常优雅的方法来实现这个相当简单的问题,我想我看过某个人的演示或视频。
我真的需要习惯并改变我的思维方式,以React.js为导向。
只是在寻找最佳实践方法,我可以用非常丑陋和笨重的方式解决这个问题,但我喜欢React.js,因为它非常简单。
3个回答

25

尽可能将状态提升至组件层次结构的高层,并在所有下层使用不可变的props。将活动选项卡存储在您的tab-component中并基于数据(在本例中为this.props)生成菜单项,以减少代码重复。

以下是示例和Backbone路由器的工作JSFiddle: http://jsfiddle.net/ssorallen/4G46g/

var TabComponent = React.createClass({
  getDefaultProps: function() {
    return {
      menuItems: [
        {uid: 'home'},
        {uid: 'about'},
        {uid: 'contact'}
      ]
    };
  },

  getInitialState: function() {
    return {
      activeMenuItemUid: 'home'
    };
  },

  setActiveMenuItem: function(uid) {
    this.setState({activeMenuItemUid: uid});
  },

  render: function() {
    var menuItems = this.props.menuItems.map(function(menuItem) {
      return (
        MenuItem({
          active: (this.state.activeMenuItemUid === menuItem.uid),
          key: menuItem.uid,
          onSelect: this.setActiveMenuItem,
          uid: menuItem.uid
        })
      );
    }.bind(this));

    return (
      React.DOM.ul({className: 'nav navbar-nav'}, menuItems)
    );
  }
});

除了添加一个类名和公开点击事件外,MenuItem 几乎无法执行任何操作:

var MenuItem = React.createClass({
  handleClick: function(event) {
    event.preventDefault();
    this.props.onSelect(this.props.uid);
  },
  render: function() {
    var className = this.props.active ? 'active' : null;

    return (
      React.DOM.li({className: className},
        React.DOM.a({href: "#" + this.props.uid, onClick: this.handleClick})
      )
    );
  }
});

但是技术部分,this.props.active ? 'active' : null;active: (this.state.activeMenuItemUid === menuItem.uid) 真的很管用,如此简单的表达式... - TrySpace
您可以在使用React.renderComponent渲染的根组件上调用setProps。在路由更改时,您可以通过调用setProps来设置新的活动选项卡。在我的示例中,我将活动菜单项作为状态的一部分,但也可以将其移动到属性中以实现此目的。 - Ross Allen
清楚地说,.bind() 部分确保绑定的组件上更新 propsstate 中的任一项?所以从技术上讲,我使用 props 还是 state 并不重要?它只在我想要访问它们的生命周期时才有影响。(但肯定最好在功能上划分 stateprops。)还有一件事:setPropssetState 都会触发相同的组件生命周期吗? - TrySpace
我在一个工作的JSFiddle中添加了一个Backbone路由器。尝试点击选项卡:http://jsfiddle.net/ssorallen/4G46g/ - Ross Allen
1
classSet已经过时了。您能否更新您的fiddle?https://facebook.github.io/react/docs/class-name-manipulation.html - thedanotto
显示剩余3条评论

1

-1

你可以尝试将菜单项的点击处理程序提升到其父组件中。事实上,我正在尝试做类似于你所做的事情...我有一个顶层菜单栏组件,我想使用菜单栏模型来渲染菜单栏和菜单项。其他组件可以通过向菜单栏模型添加内容来贡献给顶层菜单栏...只需添加顶层菜单、子菜单项和点击处理程序(位于添加菜单的组件中)。然后,顶层组件将呈现菜单栏界面,并在点击任何内容时使用“回调”组件的点击处理程序进行调用。通过使用菜单模型,我可以添加诸如活动/鼠标悬停/非活动等的CSS样式,以及图标之类的东西。顶层菜单栏组件可以决定如何渲染项目,包括悬停、点击等等。至少我认为它可以...因为我自己对ReactJS还是新手,仍在努力解决这个问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接