事件委托(事件代理)
学习内容与资源来自这位大佬:传送门,启动!
尤其是关于为什么要使用事件委托的原理,是原样搬运过来的:
一般来说,dom需要有事件处理程序,我们都会直接给它设事件处理程序就好了,那如果是很多的dom需要添加事件处理呢?比如我们有100个li,每个li都有相同的click点击事件,可能我们会用for循环的方法,来遍历所有的li,然后给它们添加事件,那这么做会存在什么影响呢?
在JavaScript中,添加到页面上的事件处理程序数量将直接关系到页面的整体运行性能,因为需要不断的与dom节点进行交互,访问dom的次数越多,引起浏览器重绘与重排的次数也就越多,就会延长整个页面的交互就绪时间,这就是为什么性能优化的主要思想之一就是减少DOM操作的原因;如果要用事件委托,就会将所有的操作放到js程序里面,与dom的操作就只需要交互一次,这样就能大大的减少与dom的交互次数,提高性能;
每个函数都是一个对象,是对象就会占用内存,对象越多,内存占用率就越大,自然性能就越差了(内存不够用,是硬伤,哈哈),比如上面的100个li,就要占用100个内存空间,如果是1000个,10000个呢,那只能说呵呵了,如果用事件委托,那么我们就可以只对它的父级(如果只有一个父级)这一个对象进行操作,这样我们就需要一个内存空间就够了,是不是省了很多,自然性能就会更好。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<!-- 定义:事件委托又称事件代理,利用事件冒泡的原理,
将一个父容器内的多个子元素的相同的事件类型用绑定在父元素上的一个事件处理程序,而非为子元素挨个绑定监听事件 -->
<!-- 优点:在删除一个子元素时,不用特意为其删除监听事件,而在新增一个子元素时,也不用去新增点击事件 -->
<ul id="container">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
</body>
<script>
var parent = document.getElementById("container");
var list = document.getElementsByTagName("li");
for(var i = 0;i<list.length;i++){
list[i].onclick = function(){
console.log(this.innerText);
}
}
//为什么要使用事件委托?
parent.onclick = function(){
console.log(this);//这个this是parent而不是内部的元素!
}
//那么如何使得代理的事件触发之后与绑定在原来节点上的事件作用一致?使用event对象的target属性
parent.onclick = function(ev){
var event = ev || window.event;
var target = ev.target || ev.srcElement;
if(target.nodeName.toLowerCase() == "li"){
alert(target.innerText);
//如果按钮具有不同时事件如何使用事件代理?
switch (target.innerText) {
case 1:
alert("这是1号~");
break;
case 2:
alert("这是2号~");
default:
alert("这是其他的~");
break;
}
}
}
</script>
</html>
那什么样的事件可以用事件委托,什么样的事件不可以用呢?
适合用事件委托的事件:click,mousedown,mouseup,keydown,keyup,keypress。
值得注意的是,mouseover和mouseout虽然也有事件冒泡,但是处理它们的时候需要特别的注意,因为需要经常计算它们的位置,处理起来不太容易。
不适合的就有很多了,举个例子,mousemove,每次都要计算它的位置,非常不好把控,在不如说focus,blur之类的,本身就没用冒泡的特性,自然就不能用事件委托了。
JQuery中的事件委托:
在整理时,发现jQuery从1.7之后就不推荐live()和delegate()方法了,所以尽量还是使用on()方法更好,用法就如上图,$("#parent").on('mouseover','#child')~