让我们先看这样的一个例子:创建一个一组<li>标签,实现鼠标点击哪个li标签时,便输出被点击标签内部字符的功能;
点击元素输出对应内部字符:
按照常规思路,我们需要读取标签长度,然后循环绑定onclick事件:
var omain = document.querySelector("#main");
for(var i=0;i<omain.children.length;i++){
omain.children[i].onclick = function(){
console.log(this.outerText);
this.outerText = "123";
}
}
但这种方式有两个显而易见的问题:
- 占用内存过大,当内部标签更多时,需要给每一个标签都绑定一个事件,占用了大量的内存空间,且随着循环次数的增加,耗时更长;
- 当内部标签数量数量发生变化时,循环次数也需要进行调整;
所以针对这类子元素循环绑定事件,或者动态添加元素绑定事件,我们可以通过事件委托的方式进行;
事件委托
事件委托是通过事件冒泡的原理实现,而何为事件冒泡呢?
通过这个例子可以很好的理解事件冒泡:创建三个父子级关系的嵌套div矩形,给每个矩形绑定一个onclick事件,当三个矩形被点击时,分别输出不同的结果:
但我们发现,虽然点击的是最内层的div,却输出了三个div都被点击的结果;
这就是事件冒泡的原理:当点击事件发生在最内层的div节点上是,事件就像在水底生成的气泡一样,一层一层的向上层传播这一事件,所以外层的两个div也被触发。
而事件委托就可以利用这一原理,当内部节点触发事件时,事件会传播到父节点上,此时便可以将事件委托给父节点进行;刚才对li进行点击的操作便可以更改为:
omain.onclick = function(e){
console.log(e.target.innerText);
}
这样不仅可以不用循环绑定事件,提高性能,也减少了代码量
而在上一篇前端学习记录(七)(https://blog.csdn.net/qq_33402172/article/details/119462724?spm=1001.2014.3001.5502)中,最后的双击转移这一操作也可以由循环绑定优化为事件委托:
//利用事件委托进行双击转移
om.ondblclick = function(e){
if (e.target.parentNode.id == "s1") {
os2.append(e.target);
}
else if (e.target.parentNode.id == "s2") {
os1.append(e.target);
}
}