教你应付一个很恶心却常见的需求(点击自身之外的区域关闭本身)

作前端最难受的就是产品给的需求以及测试给的bug了,看待这个标题是否是有点蒙,这是什么需求,下面来解读下!

需求

需求:以下图,点击已保存按钮弹出已保存列表,当点击屏幕其余区域要关闭这个下拉框,是否是很简单前端

加点东西,可是点击这个下拉框内部的区域不能关闭下拉框)(原谅我里面没写东西你就当有东西,给个机会噻!),是否是很常见,是否是很恶心!大家是怎么作的。 以前我见过有人把事件挂在window上,而后把不想要操做dom都挂上class,而后在点击事件里面一一排除括弧笑,或者有人投机取巧在一部分dom上挂了事件,结果又是测试不是每次都能关闭,全看运气!react

接天就来讲下个人解决办法,由于我是写的react,我就直接上react代码了,逻辑都是同样,无妨!数组

挂载事件

首先在componentDidMount中写下咱们函数的触发:dom

window.addEventListener('click', (event) => {
      event = event || window.event;

        this.setState({
          savedListShow: false, // 这个是控制列表显隐的状态
        });
    })

事件挂在window上怎么避免点击列表内部的dom不会触发呢,不要说什么阻止冒泡,很差使的,首先咱们在事件中输出咱们event,
看看究竟是什么!函数

元素挂上不想触发的识别class

这是我点击列表内部输出的event测试

说是路径,其实在深一步输出出来的是js对象,既然是js对象那咱们就能拿到对象上的calss属性了,对于咱们的判断也就不成问题了。this

去代码中到找咱们不想要触发的那个(或者是一堆)不想触发的dom的最大父级,spa

对的我这里是class为SavedList的div,在最前边(记住是最前边)加上一个class _&saveBtn(别人不用的,省得冲突)。code

点击事件中加判断排除不想触发的dom

在细看下上边我点击输出的event中的path, 每个元素.后的就是class, 注意横线处的class,这说明我点击的事件源是我不但愿触发的区域,而后咱们回到最开始componentDidMount中的事件函数。component

componentDidMount() {
    // 点击其余区域关闭已保存条件弹窗
    window.addEventListener('click', (event) => {
      event = event || window.event;

      let isSaveStructure = event.path.some(item => {
      这里使用了startsWith,相对来讲比较严谨,这要是为何强调要在最前边添加的缘由了
        if (item.className && item.className.startsWith('_&saveBtn')) {
          return true;
        }
      });

      if (!isSaveStructure) {
        this.setState({
          savedListShow: false
        });
      }
    })
  }

这样依赖咱们不想触发的dom以及dom内部的元素,遇到这个点击事件就会呗排除在外了,是否是很省心。

总结

  • 添加事件 window.addEventListener('click', (event) => {})
  • 在不想触发的dom的最大父级上添加用于区分的class,好比classSavedList的div以及内部dom不须要触发那就在SavedList上添加须要识别的class, 主要要避免和其余人的冲突,最好是特殊一点;
  • 在以前写好的实践中,判断注意path里面的是一个数组,包含的是js对象,抓取返回回来的classNamestring类型,不是数组,咱们判断使用的是startsWith();
相关文章
相关标签/搜索