事件代理中如何快速排除指定元素
前言
在事件代理中,往往有的时候我们需要生效的部分会存在其他元素影响,比如我可能需要响应一个卡片的点击事件,但是这个卡片里面自身又有其它link元素,比如卡片的分类,tag标签等,当我们点击分类或者tag标签,由于事件冒泡的原因,他也会触发事件代理的click事件,也就是父级元素的click事件。
但是显然我们不需要响应他们,如果单纯通过event.target
去排查,是不够完善的,有可能这个target是一个无class的元素,或者是同时存在多个的元素,我们可能还希望通过指定他们的父级元素class来进行排除。
教程
const blackClassList = ["article-card-tag", "comments", "article-card-category"];
const wrap = document.querySelector(".article-card-wrap");
wrap.addEventListener("click", function(event) {
const target = event.target;
const parent = target.closest(".article-card");
if (!parent) return;
//如果点击的元素是黑名单className则不执行
const isBlack = this.hasBlackClass(target, parent);
if (isBlack) return;
// 实际要响应的逻辑操作
});
function hasBlackClass(target, parent): boolean {
// 当前target是否黑名单元素
const isBlackTarget = Array.from(target.classList).find((className) => blackClassList.includes(className));
if (isBlackTarget) return true;
// 当前target的父级是否黑名单元素
const blackDomList = blackClassList.flatMap((className) =>
Array.from(parent.querySelectorAll(`.${className}`))
);
const isBlackChild = blackDomList.find((black) => black.contains(target));
if (isBlackChild) return true;
return false;
}
实现逻辑也很简单,首先我们要有一个范围,这个范围就是target点击的卡片容器,也就是parent
元素,我们通过closest
获取到。
然后我们先判断target元素本身是否就是黑名单中的元素,如果是,就返回true。
然后我们通过卡片来获取卡片里面的黑名单元素,通过新增的flatMap
方法,将满足条件的元素打平成一个数组,然后查询数组中的元素是否包含target,如果包含,说明target是黑名单元素的child,我们返回true。
最后以上条件都不满足,返回false。
这种方式比通过递归获取target的父级,然后判断父级是否是黑名单元素性能更好,效率更高,唯一缺点就是每次事件都需要querySelectorAll
查询一次黑名单元素,如果是点击相同卡片就会有一些浪费,解决办法就是加入缓存功能,但是由于我的博客主题不太有这种操作,所以就省略了。
分类:
JavaScript
标签:
javascript事件代理
版权申明
本文系作者 @木灵鱼儿 原创发布在木灵鱼儿站点。未经许可,禁止转载。
暂无评论数据