如何在 btn-click 上打开和关闭下拉菜单,但同时与外部点击关闭? [英] How to open and close dropdown on btn-click, but in same time with outside click close?

查看:29
本文介绍了如何在 btn-click 上打开和关闭下拉菜单,但同时与外部点击关闭?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有在 btn 单击时打开的下拉列表.

 toggleAllCategories() {this.setState({ isOpenAllCategories: !this.state.isOpenAllCategories });}

也在外部点击下拉菜单中关闭.

 handleClickOutside(event) {如果 (this.wrapperRef && !this.wrapperRef.contains(event.target)) {this.toggleAllCategories();}}

但问题是我无法通过单击按钮打开和关闭下拉菜单.

当我点击两次按钮下拉菜单仍然打开时,外部点击实现的原因.

如何在按钮上设置togglebleDroopdown并同时在外部点击时关闭?

STACKBLITZ 现场示例: https://stackblitz.com/edit/react-coihzv?file=index.js

这是下拉菜单和整个相关逻辑的组件和整个实现:

class AllCategories 扩展组件 {构造函数(道具){超级(道具);this.state = {allCategories: getAllCategoriesList(),isOpenAllCategories: false};}componentDidMount() {document.addEventListener('mousedown', this.handleClickOutside.bind(this));}componentWillUnmount() {document.removeEventListener('mousedown', this.handleClickOutside.bind(this));}setWrapperRef(节点){this.wrapperRef = 节点;}handleClickOutside(事件){如果 (this.wrapperRef && !this.wrapperRef.contains(event.target)) {this.toggleAllCategories();}}切换所有类别(){this.setState({ isOpenAllCategories: !this.state.isOpenAllCategories });}使成为() {返回 (<片段><AllCategoriesButton toggleAllCategories={this.toggleAllCategories}/>{this.state.isOpenAllCategories ?(<div className="all-categories-wrapper" ref={(node) =>this.setWrapperRef(node)}><div className="all-categories"><ul className="all-categories-list"><li className="all-categories-list-item">所有类别</li>{this.state.allCategories.map((category) => ())}

) : ('')}</片段>);}}

解决方案

您可以使用 event.target.tagName 检查触发点击的元素.

因此,为了防止切换两次,您可以执行以下操作:

 handleClickOutside(event) {if (this.wrapperRef && !this.wrapperRef.contains(event.target) &&event.target.tagName.toLowerCase() !== 'button') {this.toggleAllCategories();}}

<小时>

另一种方法

  • 为按钮创建一个引用,将其命名为 buttonRef.

现在将 handleClickOutside 更新为:

handleClickOutside(event) {if (this.wrapperRef && !this.wrapperRef.contains(event.target) &&event.target !== buttonRef.current) {this.toggleAllCategories();}}

这样会更合适.

希望这有帮助!

I have dropdown which is open on btn click.

  toggleAllCategories() {
    this.setState({ isOpenAllCategories: !this.state.isOpenAllCategories });
  }

Also on outside click dropdown is closed.

  handleClickOutside(event) {
    if (this.wrapperRef && !this.wrapperRef.contains(event.target)) {
      this.toggleAllCategories();
    }
  }

But problem is cus I can't open and close dropdown by clicking on button.

When I click two times on the button dropdown is still open, cus of outside click implementation.

How to make togglebleDroopdown on button and close on outside click in same time?

STACKBLITZ live example: https://stackblitz.com/edit/react-coihzv?file=index.js

This is component and whole implementation of dropdown and entire related logic:

class AllCategories extends Component {
  constructor(props) {
    super(props);

    this.state = {
      allCategories: getAllCategoriesList(),
      isOpenAllCategories: false
    };
  }

  componentDidMount() {
    document.addEventListener('mousedown', this.handleClickOutside.bind(this));
  }

  componentWillUnmount() {
    document.removeEventListener('mousedown', this.handleClickOutside.bind(this));
  }

  setWrapperRef(node) {
    this.wrapperRef = node;
  }

  handleClickOutside(event) {
    if (this.wrapperRef && !this.wrapperRef.contains(event.target)) {
      this.toggleAllCategories();
    }
  }

  toggleAllCategories() {
    this.setState({ isOpenAllCategories: !this.state.isOpenAllCategories });
  }

  render() {
    return (
      <Fragment>
        <AllCategoriesButton toggleAllCategories={this.toggleAllCategories} />

        {this.state.isOpenAllCategories ? (
          <div className="all-categories-wrapper" ref={(node) => this.setWrapperRef(node)}>
            <div className="all-categories">
              <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>
        ) : (
          ''
        )}
      </Fragment>
    );
  }
}

解决方案

You can check the element in which the click was triggered using event.target.tagName.

So to prevent toggling twice you can do the following:

 handleClickOutside(event) {
    if (this.wrapperRef && !this.wrapperRef.contains(event.target) &&event.target.tagName.toLowerCase() !== 'button') {
      this.toggleAllCategories();
    }
  }


EDIT: Another Approach

  • Create a ref for the button lets name it buttonRef.

Now update the handleClickOutside to this:

handleClickOutside(event) {
    if (this.wrapperRef && !this.wrapperRef.contains(event.target) &&event.target !== buttonRef.current) {
      this.toggleAllCategories();
    }
  }

This will be more appropriate way.

Hope this Helps!

这篇关于如何在 btn-click 上打开和关闭下拉菜单,但同时与外部点击关闭?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
前端开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆