JS中的事件代理与事件委派的技巧
概念
事件委托(事件代理),就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。
为什么要用事件委托
在有很多的dom需要添加事件处理时,比如我们有100个li,每个li都有相同的click点击事件,可能我们会用for循环的方法,遍历所有的li,给每一个添加事件处理程序,但是这么做,会对性能造成很大影响。
在JavaScript中,添加到页面上的事件处理程序数量将直接关系到页面的整体运行性能,因为需要不断地与dom节点进行交互,访问dom的数量越多,引起浏览器回流和重绘的次数也就越多,就会延长整个页面的交互就绪时间,这就是为什么性能优化的主要思想之一就是减少DOM操作的原因。
而如果使用了事件委托,就会将所有的操作放到js程序里面,与dom的操作就只需要交互一次,这样就能大大的减少与dom的交互次数,提高性能。
每个函数都是一个对象,是对象就会占用内存,对象越多,内存占用率就越大,自然性能就越差,比如100个li,就要占用100个内存空间,如果是1000就要占用1000个内存空间。
如果使用事件委托,那么我们就可以只对它的父级对象进行操作,这样我们就需要一个内存空间就够了,大量的节省了内存,提高了性能。
事件委托的原理
事件委托是利用事件的冒泡原理来实现的。
事件冒泡:是事件从最深层的节点开始,逐步向上传播事件,例:页面上有一个节点树,div>ul>li>a
,给最里面的a加一个click点击事件,那么这个事件会一层一层的向外抛出,执行顺序是a>li>ul>div
,在这种情况下,给最外面的div加点击事件,那么里面的ul,li,a触发点击事件时,都会冒泡到最外层的div上进行触发,这就是事件委托,既委托它们父级代为执行事件。
事件代理(委托)实现
不使用事件委托的实现方式:
<body>
<ul id="uli">
<li>111</li>
<li>222</li>
<li>333</li>
</ul>
<script>
window.onload = function() {
let ul = document.getElementById('uli');
let ali = document.querySelectorAll('li');
for(let i=0;i<ali.length;i++) {
ali[i].onclick = function() {
alert(123);
}
}
}
</script>
</body>
使用事件委托的方式:
<body>
<ul id="uli">
<li>111</li>
<li>222</li>
<li>333</li>
</ul>
<script>
window.onload = function() {
let ul = document.getElementById('uli');
ul.onclick = function() {
alert(123);
}
}
</script>
</body>
这里用父级<ul>
做事件处理,当<li>
被点击时,由于冒泡原理,事件就会冒泡到<ul>
上,因为<ul>
上有点击事件,所以事件就会触发。
但是这时点击ul,事件同样也会被触发。如何避免这种情况?Event对象提供了一个属性叫target
,可以返回事件的目标节点,我们称为事件源,也就是说,target就可以表示为当前的事件操作的dom,但不是真正操作dom。兼容情况:标准浏览器用ev.target,IE浏览器用event.srcElement。实现如下:
<body>
<ul id="uli">
<li>111</li>
<li>222</li>
<li>333</li>
</ul>
<script>
window.onload = function() {
let ul = document.getElementById('uli');
ul.onclick = function(event) {
let event1 = event || window.event;
let target = event1.target || event1.srcElement;
console.log(target);
if(target.nodeName.toLowerCase() === 'li'){
alert(123);
alert(target.innerHTML);
}
}
}
</script>
此时就只有点击li会触发事件了,且无论li的数量有多少,每次都只执行一次dom操作。
总结
适合事件委托的事件有:click , mousedown , mouseup, keydown, keyup , keypress
。
优点:
- 减少整个⻚⾯所需的内存,提升整体性能;
- 动态绑定,减少重复操作;
局限性:
-
focus 、 blur
这些事件没有事件冒泡机制,所以⽆法进⾏委托绑定事件。 - mousemove 、 mouseout 这样的事件,虽然有事件冒泡,但是只能不断通过位置去计算定位, 对性能消耗⾼,因此也是不适合于事件委托的。
上一篇: 事件委托
下一篇: 利用事件委托优化JavaScript编程