ReactJS下拉菜单,打开当前之前关闭其他菜单

问题描述 投票:1回答:4

我已经取得了一些下拉菜单:

export default class DropdownMenu extends Component {

    constructor(props) {
        super(props)

        this.state = {
            menuOpen: false,
            highlight: false,
            count: this.props.count | 0
        }
        this.showDropdown = this.showDropdown.bind(this);
    }

    componentDidMount() {

    }

    showDropdown() {
            this.setState({
                menuOpen: !this.state.menuOpen
            });
    }

    render() {
        return <div className="dropdown__menu" onClick={this.showDropdown}>
            {this.props.text} {this.state.count > 0 ? <b>{this.state.count}</b> : ''}
            <div className="dropdown__content" style={this.state.menuOpen ? {'display': 'block'} : {'display': 'none'}}>
                {this.props.children}
            </div>
        </div>
    }
}

问题是,你可以把它们全部打开,让他们开到你点击它们再次关闭它们。如何让这个任何其他菜单是开放的,如果另一个打开被关闭?


这里是他们实现:

render() {
        ...
                <div className="filter_container">
                    <DropdownMenu text="New" count={127} disabled/>
                    <DropdownMenu text="Only show">
                        <li>New</li>
                        <li>Old</li>
                    </DropdownMenu>
                    <DropdownMenu text="Other">
                        <li>one</li>
                        <li>two</li>
                    </DropdownMenu>
                    <DropdownMenu text="Sort by">
                        <li>Name</li>
                        <li>Age</li>
                        <li>Value</li>
                    </DropdownMenu>
                </div>
            </div>
...
javascript reactjs
4个回答
0
投票

由于反应过来了一个单向数据流,你需要做到这一点的父组件

import React from 'react'

class DropdownParent extends React.Component {

  state = {
    openedDropdown: null,
  };

  render() {
    return (
      <React.Fragment>
        <Dropdown
          name="dropdown1"
          isOpen={this.state.openedDropdown === 1}
          onClick={() => this.setState({ openedDropdown: 1 })}
          onClose={() => this.setState({ openedDropdown: null })}
        />
        <Dropdown
          name="dropdown2"
          isOpen={this.state.openedDropdown === 2}
          onClick={() => this.setState({ openedDropdown: 2 })}
          onClose={() => this.setState({ openedDropdown: null })}
        />
      </React.Fragment>
    )
  }
}

然后你需要下拉列表是基于props.isOpen,而不是你的state.menuOpen和使用props.onClick / props.onClose代替this.showDropdown

另外,您可以立足于鼠标(如onmousedown事件OnMouseEnter在...)或聚焦(聚焦状态的onblur)事件,但是这是很难让移动友好的,并不会保证你关于“在同一时刻只有一个下拉菜单”。更多信息:https://reactjs.org/docs/events.html


0
投票

由于是开放不是封装在下拉菜单中的状态的信息了,我建议了移动了这个信息到父组件的状态。

您现在应该转换成下拉框无国籍功能:

const DropdownMenu = ({ menuOpen, count, text, showDropdown }) => ( //props deconstruction
    <div className="dropdown__menu" onClick={showDropdown}>
        {text} 
        {count && <b>{count}</b>} //If you do not want to show anything if a condition is falsy, use the inline if &&
        <div className="dropdown__content" style={{ 'display': menuOpen ? 'block' : 'none' }}> //You can put the ternary condition directly into the JSON
            {this.props.children}
        </div>
    </div>
)

现在,您将需要存储哪些下拉在父组件被打开:

class Parent extends Component {
    state = {
        openedDropdown = null;
    }

并发送一个回调函数,以您的下拉列表:

dropdownClicked = openedDropdown => ev => {
    this.setState({ openedDropdown })
}

<DropdownMenu text="New" count={127} disabled showDropdown={this.dropdownClicked('New')}  menuOpen={this.state.openedDropdown === 'New'}/>
<DropdownMenu text="Only show" showDropdown={this.dropdownClicked('Only')}  menuOpen={this.state.openedDropdown === 'Only'}>
    <li>New</li>
    <li>Old</li>
</DropdownMenu>
<DropdownMenu text="Other" showDropdown={this.dropdownClicked('Other')}  menuOpen={this.state.openedDropdown === 'Other'}>
    <li>one</li>
    <li>two</li>
</DropdownMenu>
<DropdownMenu text="Sort by" showDropdown={this.dropdownClicked('Sort')}  menuOpen={this.state.openedDropdown === 'Sort'}>
    <li>Name</li>
    <li>Age</li>
    <li>Value</li>
</DropdownMenu>

0
投票

因为它失去了被点击时,另一个被关注你可以玩onBlur

class DropDown extends React.Component {
  state = {
    isVisible: false
  }
  
  closeMenu = () => {
    this.setState({ isVisible: false })
  }
  
  toggleMenu = () => {
    this.setState(prevState => ({ isVisible: !prevState.isVisible }))
  }
  
  render() {
    const { isVisible } = this.state;
    return (
      <div
        className="dropdown__menu"
        onBlur={this.closeMenu}
        tabIndex={0}
        role="menu"
        onClick={this.toggleMenu}>
        {isVisible ? 'visible' : 'hidden'}
      </div>
    )
  }
}


const App = () => (
  <div>
     <DropDown />
     <DropDown />
  </div>
)
 

ReactDOM.render(<App />, document.getElementById('root'));
.dropdown__menu {
  outline: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>

0
投票

我会用终极版为。 https://redux.js.org/

该解决方案允许您为整个应用程序管理状态。它可用于存储有关打开下拉列表信息,并改变它 - 如果需要的话。

© www.soinside.com 2019 - 2024. All rights reserved.