【问题标题】:Navigation bar with active Tab without additional modules带有活动选项卡的导航栏,没有附加模块
【发布时间】:2018-06-29 12:20:52
【问题描述】:

这个问题比较简单,并没有专门连接到导航栏,这只是一个很好的例子..

我想通过使用“活动”类来创建带有活动标签突出显示的简单导航栏。目前我有两个组件:NavBar 和 NavItem。在标签点击时,我想让它处于活动状态并确保所有其他人都处于非活动状态。

什么是最简单的解决方案?如何将 NavBar 中的多个 NavItem 重置为默认的非活动状态而不单击一个?


NavBar.js

import React from 'react';

import NavItem from './NavItem';

export default class NavBar extends React.Component {

    constructor() {
        super();
        this.menuItems = [
            { name: 'HOME', url: '#' },
            { name: 'NEWS', url: '#' },
            { name: 'CONTACT', url: '#' }
    ];
    }

    render() {
        return (
            <nav>
                <ul>
                    CHOOSE:
                    {this.menuItems.map( (item,i) => <NavItem key={i} data={item} /> )}
                </ul>
            </nav>
        );
    }
}

NavItem.js

import React from 'react';

export default class NavItem extends React.Component {

    constructor() {
        super();

        this.state = {
            active: false
        }
    }

    handleOnClick() {
        this.setState({active: !this.state.active});
    }

    render() {
            let item = this.props.data;
            return <li><a href={item.url} className={this.state.active ? 'active' : ''} onClick={ (e) => this.handleOnClick(e) }>{item.name}</a></li>;
    }
}

【问题讨论】:

  • 在 NavBar 组件状态中,您可以保存当前处于活动状态的选项卡,还可以创建处理 NavBar 内的 onClick 的方法并将其作为道具传递给 NavItem。

标签: reactjs


【解决方案1】:

我没有看到将列表项放在不同组件中的好处。事实上,您最终会在 1 个列表项上设置 active 类,因为每个项目都是一个单独的组件。

最简单的方法是将列表放在同一个组件中,并在点击函数中传递一个索引。

{this.menuItems.map((item,i) => <li><a href={item.url} className={this.state.activeItem == i ? 'active' : ''} onClick = {(e) => this.handleOnClick(e,i) }>{item.name}</a></li> )}

现在点击功能看起来像 -

handleOnClick = (event, index) => {
    this.setState({activeItem: index});
  }

所以你的组件看起来像

import React from 'react';

import NavItem from './NavItem';

export default class NavBar extends React.Component {

  constructor() {
    super();
    this.menuItems = [
      {
        name: 'HOME',
        url: '#'
      }, {
        name: 'NEWS',
        url: '#'
      }, {
        name: 'CONTACT',
        url: '#'
      }
    ];

    this.state = {
      activeItem: 0
    }
  }

  handleOnClick = (event, index) => {
    this.setState({activeItem: index});
  }

  render() {
    return (
      <nav>
        <ul>
          CHOOSE: {this
            .menuItems
            .map((item, i) => <li>
              <a
                href={item.url}
                className={this.state.activeItem == i
                ? 'active'
                : ''}
                onClick=
                {(e) => this.handleOnClick(e,i) }>{item.name}</a>
            </li>)}
        </ul>
      </nav>
    );
  }
}

我已将项目设置为 0 索引默认活动,但您可以根据需要更改它。

【讨论】:

  • 很好,虽然这个解决方案将他的实现限制为一次只有一项。
【解决方案2】:

看起来 React Docs 文章 Lifting State Up 完全按照您演示的用例编写。

您正在隔离管理每个组件内的isActive 状态。 NavItem 的每个实例不知道也不应该知道NavItem 的其他实例的状态是什么

所以...提升你的状态!管理Navbar内部的活动/非活动栏信息,并通过props控制您的多个NavItem实例。

应该是这样的:

NavBar.js

import React from 'react';

import NavItem from './NavItem';

export default class NavBar extends React.Component {
  constructor() {
    super();
    this.state = {
      menuItems: [
        { name: 'HOME', url: '#', isActive: true },
        { name: 'NEWS', url: '#', isActive: false },
        { name: 'CONTACT', url: '#', isActive: false }
      ]
    };
    this.menuItems = [];
  }
  onNavItemClick = itemName => {
    const nextMenuItems = this.state.menuItems.map(item => {
      if (item.name === itemName) {
        return { ...item, isActive: true };
      }
      return { ...item, isActive: false };
    });
    this.setState({
      menuItems: nextMenuItems
    });
  };
  render() {
    return (
      <nav>
        <ul>
          CHOOSE:
          {this.state.menuItems.map((item, i) => (
            <NavItem
              key={item.name}
              name={item.name}
              isActive={item.isActive}
              onClick={this.onNavItemClick}
              url={item.url}
            />
          ))}
        </ul>
      </nav>
    );
  }
}

NavItem.js

import React from 'react';

export default class NavItem extends React.Component {
  constructor() {
    super()
    console.log()
    this.onClickFunction = () => this.props.onClick(this.props.name);
  }
  render() {
    let item = this.props.data;
    return (
      <li className={this.props.isActive ? 'active' : ''}>
        <a
          href={this.props.url}
          onClick={this.onClickFunction}
        >
          {this.props.name}``
        </a>
      </li>
    );
  }
}

【讨论】:

    【解决方案3】:

    也许你可以使用&lt;NavLink to="" activeStyle={{color: 'red'}} /&gt; 组件作为链接/选项卡(来自'react-router-dom')

    【讨论】:

      【解决方案4】:

      LiranC​​trong>,Infinity,感谢您的帮助和示例,我想我明白了。 我知道它会以向 NavBar 提升状态结束,只是不太确定如何引用特定元素..

      我希望当时只有一个元素处于活动状态,并带有列表项组件以供将来使用,因此我将其混合并想出了这样的代码。期待任何进一步的优化建议。

      NavBar.js

      import React from 'react';
      
      import NavItem from './NavItem';
      
      export default class NavBar extends React.Component {
      
          constructor() {
              super();
      
              this.menuItems = [
                  { name: 'HOME', url: '#' },
                  { name: 'NEWS', url: '#' },
                  { name: 'CONTACT', url: '#' }
              ];
      
              this.state = {
                  activeItem: null
              }
          }
      
          handleOnClick = (e,i) => {
              this.setState({activeItem: i});
          }
      
          render() {
              return (
                  <nav>
                      <ul>
                          CHOOSE:
                          {this.menuItems.map( (item,i) => 
                              <NavItem
                                  key={i}
                                  idn={i}
                                  data={item}
                                  isActive={this.state.activeItem == i ? true : false}
                                  onClick={this.handleOnClick} />
                          )}
                      </ul>
                  </nav>
              );
          }
      }
      

      NavItem.js

      import React from 'react';
      
      export default class NavItem extends React.Component {
      
          render() {
              let item = this.props.data;
      
              return (
                  <li>
                      <a 
                          href={item.url}
                          className={this.props.isActive ? 'active' : ''}
                          onClick={ (e) => this.props.onClick(e, this.props.idn) }>{item.name}
                      </a>
                  </li>
              );
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2016-10-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-02-22
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多