面试被问到事件代理(事件委托),之前没有了解过,表示一脸懵逼。。。
1.首先记住给一个元素注册多个事件的方法:
我们平常注册事件的方式是:
div1.onclick = function(){
console.log('hello');
};
div1.onclick = function(){
console.log('world');
};
//world
打印出来的结果为 :world
说明后面注册的事件覆盖了之前的事件。
所以我们要实现给一个元素添加两个事件要使用事件绑定的方法:
addEventListener(事件名称,函数,布尔值) ,布尔值默认为false,表示事件发生在冒泡阶段。
div1.addEventListener('click',function(){
console.log('hello');
},false);
div1.addEventListener('click',function(){
console.log('world');
},false);
//hello
//world
2.熟悉下事件流。
事件流描述的是页面接收事件的顺序。
事件流包括三个阶段:事件捕获阶段、处于目标阶段、事件冒泡阶段。
事件捕获
当一个事件触发后,从Window对象触发,不断经过下级节点,直到目标节点。在事件到达目标节点之前的过程就是捕获阶段。所有经过的节点,都会触发对应的事件
事件冒泡
当事件到达目标节点后,会沿着捕获阶段的路线原路返回。同样,所有经过的节点,都会触发对应的事件
通过例子理解两个事件机制:
例子1:假设有body和body节点下的btn均有绑定了一个注册事件.
效果:
当为事件冒泡(useCapture:false)时,先执行btn的事件,再执行body的事件
document.body.addEventListener('click',function(){
console.log('body')
},false);
btn.addEventListener('click',function(){
console.log('btn')
},false);
当为事件捕获(useCapture:true)时,先执行body的事件,再执行btn的事件
document.body.addEventListener('click',function(){
console.log('body')
},true);
btn.addEventListener('click',function(){
console.log('btn')
},false);
例子2:
<script>
window.onload = function() {
let dog = document.getElementById('dog');
let a1 = document.getElementById('a1');
a1.addEventListener('click', () => console.log('a1'), true); // a1新增一个事件捕获
a1.addEventListener('click', () => console.log('a1 12'), false);// a1新增一个事件冒泡
dog.addEventListener('click', () => console.log('dog12'), false);// dog新增一个事件冒泡
dog.addEventListener('click', () => console.log('dog'), true);// dog新增一个事件捕获
}
</script>
</head>
<body>
<div id="dog">
dog
<div id="a1">
a1
</div>
</div>
</body>
点击a1,
流程图
3.使用事件委托的好处
- 提高性能:事件处理程序数量过多会占用大量内存,解决办法为事件委托。添加一个事件处理程序代理所有事件。(用到事件冒泡)
- 动态监听:使用事件委托可以自动绑定动态添加的元素,即新增的节点不需要主动添加也可以一样具有和其他元素一样的事件。
例子1:
虽然没有给div2和div3添加点击事件,但是无论是点击div2还是div3,都会打印当前节点。因为其父级绑定了点击事件,点击div2后冒泡上去的时候,执行父级的事件。<script> window.onload = function(){ var div1 = document.getElementById('div1'); div1.addEventListener('click',function(e){ console.log(e.target); },false) } </script> </head> <body> <div id="div1"> <div class="child">div2</div> <div class="child">div3</div> </div> </body>
例2:<script> window.onload = function(){ var div1 = document.getElementById('div1'); div1.addEventListener('click',function(e){ console.log(e.target); },false); var div4 = document.createElement('div'); div4.setAttribute('class','child'); div4.innerHTML = 'div4'; div1.appendChild(div4); } </script> </head> <body> <div id="div1"> <div class="child">div2</div> <div class="child">div3</div> </div> </body> //这样无论后代新增了多少个节点,一样具有这个点击事件的功能。因为其父级绑定了点击事件,点击div4后冒泡上去的时候,执行父级的事件。