如何在按钮单击时切换下拉菜单并在外部单击时关闭?

Posted

技术标签:

【中文标题】如何在按钮单击时切换下拉菜单并在外部单击时关闭?【英文标题】:How have toggle dropdown on button click and close on outside click? 【发布时间】:2019-11-29 02:30:15 【问题描述】:

我有下拉菜单,通过单击按钮打开并在外部单击时关闭。

这是切换下拉菜单的功能:

toggleAllCategories = () => 
  this.setState( isOpenAllCategories: !this.state.isOpenAllCategories );
;

这意味着通过单击按钮您应该打开和关闭下拉菜单。

但在同一时间,我使用react-refs 实现了在下拉列表主体之外单击 ---> 关闭下拉列表。

使错误-再现:

第 1 步:点击“所有类别”按钮

结果:下拉菜单打开

第 2 步:再次点击“所有类别”按钮 - 想要关闭下拉菜单

结果:结果下拉菜单已打开。

    点击“所有类别”btn(状态已更改 isOpenAllCategories = true)

这就是问题所在 --> 2. 再次单击“所有类别”按钮

首先调用handleOutsideClick() 函数,该函数设置isOpenAllCategories on false

然后调用toggleAllCategories(),它在当前值isOpenAllCategories: !this.state.isOpenAllCategories 的对面改变状态,即true cus handleOutsideClick() 已经在false 上改变状态。

所有类别下拉组件:

class AllCategories extends Component 

  componentDidMount() 
    document.addEventListener('mousedown', (e) => this.handleClickOutside(e));
  

  componentWillUnmount() 
    document.removeEventListener('mousedown', (e) => this.handleClickOutside(e));
  

  setWrapperRef(node) 
    this.wrapperRef = node;
  

  handleClickOutside = (event) => 
    if (this.wrapperRef && !this.wrapperRef.contains(event.target)) 
      this.props.closeAllCategories();
    
  ;

  render() 
    return (
      <div className="all-categories-wrapper">
        <div className="all-categories" ref=(node) => this.setWrapperRef(node)>
          <ul className="all-categories-list">
            <li className="all-categories-list-item">All Categories</li>
            this.state.allCategories.map((category) => (
              <li
                className=`all-categories-list-item $
                  category.selected ? 'all-categories-list-item-active' : ''
                `
              >
                category.name
              </li>
            ))
          </ul>
        </div>
      </div>
    );
  

所有类别按钮组件:

export default ( toggleAllCategories, className ) => (
  <div className="category" onClick=() => toggleAllCategories() role="button">
    <div className=`category-button-wrapper $className`>
      <button className="category-button">
        Sports <span className="category-button-slash">/</span> Football
      </button>
      <div className="category-icon-box">
        <span className="category-icon">
          <i className="material-icons md-30 md-white">expand_more</i>
        </span>
      </div>
    </div>
  </div>
);

【问题讨论】:

【参考方案1】:

由于组件函数中的 this 范围,代码无法正常工作。您必须在组件的构造函数中绑定函数。或者将你的函数更改为 ES6 来解决这个问题

//binding
constructor(props)
  super(props)
this.handleClickOutside = this.handleClickOutside.bind(this);

handleClickOutside = () => 
 //code here

【讨论】:

我这样绑定:this.setWrapperRef = this.handleClickOutside.bind(this); 问题现在是 cus 外部点击不起作用。 不是这样的。你必须在你的构造函数中绑定。 现在尝试使用该方法this.handleClickOutside = this.handleClickOutside.bind(this); 它的工作方式相同。按钮不切换下拉菜单,外部点击工作正常... 对组件和 JSX 中的所有用户定义函数执行相同的绑定,记得添加 this.toggleAllCategories() 。你省略了这个

以上是关于如何在按钮单击时切换下拉菜单并在外部单击时关闭?的主要内容,如果未能解决你的问题,请参考以下文章

在内部单击时保持 Bootstrap 下拉菜单打开

如何在外部点击时关闭下拉菜单?

当用户在菜单外单击时,如何关闭 Bootstrap 导航栏下拉菜单?

单击时菜单不切换(关闭)

防止在外部单击时以弹出模式关闭单元格编辑器

在 div 下拉菜单之外单击时隐藏,但未显示切换