具有活动选项卡的导航栏,没有其他模块

时间:2018-06-29 12:20:53

标签: reactjs

这个问题很简单,没有专门与导航栏相连,这只是一个很好的例子。

我想使用'active'类创建带有活动标签突出显示的简单导航栏。目前,我有两个组件: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>;
    }
}

4 个答案:

答案 0 :(得分:0)

我看不到将列表项放在其他组件中的好处。实际上,由于每个项目都是一个单独的组件,您最终将在一个列表项上设置active类。

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

{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的索引设置为活动状态,但是您可以根据需要进行更改。

答案 1 :(得分:0)

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

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

所以...提升您的状态!在Navbar内部管理有关活动/非活动条的信息,并通过道具控制多个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>
    );
  }
}

答案 2 :(得分:0)

也许您可以将<NavLink to="" activeStyle={{color: 'red'}} />组件用作链接/标签(来自“ react-router-dom”)

答案 3 :(得分:0)

LiranC 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>
        );
    }
}