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

Posted

技术标签:

【中文标题】使用 React.js 在选项卡上切换类【英文标题】:Switch class on tabs with React.js 【发布时间】:2014-04-23 01:22:46 【问题描述】:

所以我有一个 tab-component 有 3 个项目:

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

.renderMenuItem 中:

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

每次我点击一个项目时,都会调用一个主干路由器,然后它会调用tab-component,而后者又会调用page-component

我仍在努力理解基本上是单向数据流的事实。而且我已经习惯了直接操作 DOM。

我想做的是将.active 类添加到单击的选项卡中,并确保将其从不活动的选项卡中删除。

我知道 CSS 技巧,您可以使用 data- 属性并对 truefalse 属性应用不同的样式。

主干路由器已经获得变量uid并调用正确的页面。我只是不确定如何最好地在选项卡之间切换类,因为只有一个可以同时处于活动状态。

现在我可以保留一些关于哪个选项卡被选中和被选中的记录,并切换它们等等。但是 React.js 已经有了这个记录保存功能。

你看到的@handleClick,我什至不想使用,因为路由器应该告诉tab-component 哪个给className: '.active' 而我想避免使用jQuery,因为React.js 没有需要直接的 DOM 操作。

我已经用@state 尝试了一些东西,但我确信有一种非常优雅的方法可以实现这个相当简单,我想我看过一些演示文稿或有人这样做的视频。

我真的必须习惯并改变我的思维方式,以响应式思考。

只是在寻找一种最佳实践方式,我可以用一种非常丑陋和笨重的方式来解决它,但我喜欢 React.js,因为它是如此简单。

【问题讨论】:

【参考方案1】:

将状态尽可能地推到组件层次结构的上层,并在下面的所有级别上处理不可变的props。将活动选项卡存储在 tab-component 中并生成菜单项关闭数据(在本例中为 this.props)以减少代码重复似乎是有意义的:

以下示例的工作 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)
      )
    );
  
);

【讨论】:

谢谢,这为我解决了很多问题,但是,我正在处理路由器,并且似乎调用:React.renderComponent( TabComponent( uid: 'home' ) ),当 URL 更改时,会触发一系列组件在反应的逻辑中,火吃掉了一切。阅读 cmets:jsfiddle.net/TrySpace/9a7TA/2 但是技术部分,this.props.active ? 'active' : null;active: (this.state.activeMenuItemUid === menuItem.uid) 确实成功了,如此简单的表达...... 您可以在使用React.renderComponent 调用呈现的根组件上调用setProps。在路线更改时,您可以通过调用setProps 设置新的活动选项卡。在我的示例中,我将活动菜单项设置为状态的一部分,但可以将其移至道具以使这成为可能。 要清楚,.bind() 部分确保 propsstate 在其绑定组件上更新?因此,从技术上讲,我是否使用propsstate 并不重要?只在生命周期中的哪个时刻我希望能够访问它们很重要。 (但肯定最好将stateprops 功能分开。)最后一件事:setPropssetState 都触发相同组件的生命周期? classSet 已弃用。你能更新你的小提琴吗? facebook.github.io/react/docs/class-name-manipulation.html【参考方案2】:

您可以尝试react-router-active-componet - 如果您使用 boostrap 导航栏。

【讨论】:

【参考方案3】:

您可以尝试将菜单项单击处理程序推送到它的父组件。实际上,我正在尝试做与您正在做的事情类似的事情。我有一个***菜单栏组件,我想使用菜单栏模型来呈现菜单栏和项目。其他组件可以通过添加到菜单栏模型来为***菜单栏做出贡献……只需添加***菜单、子菜单项和单击处理程序(在添加菜单的组件中)。然后,***组件将呈现菜单栏 UI,当单击任何内容时,它将使用“回调”组件单击处理程序来调用。通过使用菜单模型,我可以为actice/mouseover/inactive等添加css样式,以及图标等。***菜单栏组件然后可以决定如何呈现项目,包括鼠标悬停、点击等。至少我认为它可以.. 仍然在处理它,因为我自己是 ReactJS 的新手。

【讨论】:

以上是关于使用 React.js 在选项卡上切换类的主要内容,如果未能解决你的问题,请参考以下文章

javascript 当用户失去对站点的焦点时,切换浏览器选项卡上的文本(标题)(切换选项卡)

如何在选项卡栏控制器中更新选项卡上的视图

如何从另一个选项卡上的场景切换或弹出选项卡式应用程序中第一个选项卡的第二个场景?

如何使用 ViewPager 在 TabLayout 的选项卡上设置页面标题

如何同时切换 tab 和 pushViewController?

选项卡,在第一个选项卡上隐藏上一个,在最后一个选项卡上隐藏下一个