JS 点击某元素以外的地方触发事件

49 篇文章 1 订阅
34 篇文章 2 订阅

需求:点击当前元素之外的任何一个地方或者区域都需要隐藏当前元素,点击当前元素的任何一个地方,当前元素依然显示。如下面:点击颜色画板的任何一个区域,选择对应的功能。点击颜色画板之外的区域,隐藏颜色画板。

解决这个问题的核心关键还是利用event对象

到这个时候,我们应该打开浏览器,获取点击事件之后请一定要打开看一下!找一下里面有什么属性是可以加以利用的。(这里只讲关键的,不讲解全部的event对象里的所有属性参数方法)

target: 当前点击元素的DOM信息(在其他事件里面就是派发事件的目标元素)

path: 这里汇集了触发事件的DOM元素和其上层的节点的DOM信息(这会一直追溯到Window),它获取到的内容和下面方法获取到的内容是完全一样的。

document.addEventListener('mousedown', (e) => {
    console.log(e)
})
let a = document.getElementsByClassName('demo')[0]
let arr = []
arr.push(a)	 // 先推入当前元素
getParent(a) // 执行递归
arr.push(window) // 最后再加一个window
function getParent(obj) {
    if (obj.parentNode) { // 往树的上层追溯,直到最上层
        arr.push(obj.parentNode)
    } else {
        return
	}
    getParent(obj.parentNode) // 递归追溯源头
}

现在,有了这俩元素之后,接下来,我们该咋用,先看代码,等会儿再讲解!

let ObjStatus = document.getElementsByClassName('status')[0]
document.addEventListener('mousedown', (e) => {
    let t = document.getElementsByClassName('demo')[0] // 最外层元素
    if (!e.path.includes(t)) {
        ObjStatus.innerHTML = '事件触发情况:触发'
	} else {
        ObjStatus.innerHTML = '事件触发情况:未触发'
	}
})

原理讲解
        本来就只是使用e.target就行了,但是点击事件的target的机制问题,单纯地使用e.target并不能根本解决这个问题,因为目标区域内可能有很多的元素,这个点击事件会选择其内部的元素,就举当前的html代码为例子,现在我的目标区域demo内有一个p标签,如果我点到这个p标签,e.target会指向这个p标签,而不会去指向这个demo元素。又因为这个e.path含有当前元素和其所有的祖宗元素,所以可以查找e.path是否有这个demo元素,如果有,那么这个元素就是属于demo元素的内部的元素(这需要排除一些特殊情况,比如绝对布局和使用了transform的元素。),那就是说,如何点击了demo元素外的其他元素,那么当前捕获的e.path里面绝不会有demo元素。

总结
这个功能多用于关闭自己设置的弹窗,设置好最外层的判断元素,点击弹窗之外,弹窗就会关闭,这个在用户体验方面是非常有利的一个功能。

 

React Hooks 中的用法可参考

// 监听showChromePicker是否显示,显示之后增加下面这两个事件
const [showChromePicker, setShowChromePicker] = useState<boolean>(false);

// 监听windows点击颜色画板区域
useEffect(() => {
    document.addEventListener('mousedown', handleClickOutside, true);
    document.addEventListener('click', handleClickOutside, true);
    return () => {
      document.removeEventListener('mousedown', handleClickOutside, true);
      document.removeEventListener('click', handleClickOutside, true);
    };
}, [showChromePicker]);

点击之后的操作逻辑

// 递归查找父级是否在颜色画板中,不在则隐藏颜色画板
const handleClickOutside = (event: any) => {
    if (showChromePicker) {
      let arr: any = [];
      getParent(event.target) // 执行递归
      function getParent(obj: any) {
        if (obj.parentNode) { // 往树的上层追溯,直到最上层
          arr.push(obj.parentNode)
        } else {
          return
        }
        getParent(obj.parentNode) // 递归追溯源头
      }
      let chromePicker = document.getElementsByClassName('chrome-picker')[0] // 颜色画板的最外层元素类名
      // 检测是否存在于arr中,不存在则说明点击的不是内部元素,否则点击的是颜色面板中的某个区域,然后做相应显示隐藏操作
      if (!arr.includes(chromePicker)) {
        setShowChromePicker(false);
      }
    }
};

交流

公众号:公众号「进军全栈攻城狮」 ,对前端技术保持学习爱好者。我会经常分享自己所学所看的干货,在进阶的路上,共勉!

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值