image
前言
很久没有在简书上写blog,都在github上写了,看有点时间就搬运一下
关于事件委托的概念和原理就不多说,自行Google。
二层元素实现的委托
二层元素实现的委托是我自己定义的名称,具体是如下的场景
<div id="tab">
<a href="javascript:;" title="left">left</dl>
<a href="javascript:;" title="right">right</dl>
</div>
然后将事件绑定在id="tab"
元素上。这样的场景也是在比较多的,高程对事件委托的解析也是用以上差不多的代码解析的,具体实现是这样的:
先是将事件绑定在id="tab"
元素上,点击是判断title,title === ‘left’
时触发left的逻辑,否则触发right
的逻辑
document.querySelector('#tab')
.addEventListener('touchstart', e => {
const target = e.target;
if(target.title === 'left') {
// left的逻辑代码
} else {
// right的逻辑代码
}
}, false);
这样的代码乍看之下貌似没有问题,但是,加入是下面的html代码就会出现bug:
<div id="tab">
<a href="javascript:;" title="left"><img src="left_icon.png"> left</a>
<a href="javascript:;" title="right"><img src="right_icon.png"> right</a>
</div>
当点击a便签的图标,就会出现bug,只要是点击中图标,无论是点击left还是right都会是触发right的逻辑,
为什么?因为点击中icon的话,e.target
是img便签,而不是a便签,而img并没有title,如果你说可以给img便签也可以添加title,但这不是一个之便不治本的解决方案吗?加入a便签内有更多的后代元素怎么办?全都添加title吗?明显不现实。
event.path属性实现委托
使用console.log(e)
点path属性,你可以卡到path是一个数组
image
升序正好是冒泡顺序,正好可以利用这个顺序实现多层元素的事件委托。
document.querySelector('#tab')
.addEventListener('touchstart', e => {
const path = e.path;
for (let index = 0; index < path.length; index++) {
const element = path[index];
if(element.title === 'left') {
// left
break;
} else if(element.title === 'right') {
// right
break;
}
}
}, false);
event.composedPath()
虽说以上代码已经可以实现多级元素的事件委托,但是不幸的是path的兼容性是比较差[捂脸]
image
看上面的引用,可以知道path
并非标准的,而composedPath
才是标准的,但也是比较新的,换言之,兼容性也不会有多好,但path
和composedPath
一起使用,兼容必然会更高。
document.querySelector('#tab')
.addEventListener('touchstart', e => {
const path = e.path || e.composedPath();
for (let index = 0; index < path.length; index++) {
const element = path[index];
if(element.title === 'left') {
// left
break;
} else if(element.title === 'right') {
// right
break;
}
}
}, false);
小结
以上实现委托的方法是我自己自行意淫的,是不是主流实现方法?我还还没有去验证,先留个坑,谁那么巧合看到了我的文章,有更好的想法,或者主流方法实现,请不吝赐教。