<div class="big">
<div class="center">
<div class="small"></div>
</div>
</div>
<style>
.big{
width: 300px;
height: 300px;
background-color:red;
}
.center{
width: 200px;
height: 200px;
background-color:yellow;
}
.small{
width: 100px;
height: 100px;
background-color:blue;
}
</style>
<script>
let big=document.querySelector('.big')
let center=document.querySelector('.center')
let small=document.querySelector('.small')
big.onclick=function(){
console.log('我是big');
}
center.onclick=function(){
console.log('我是center');
}
small.onclick=function(){
console.log('我是small');
}
</script>
此时点击small,会输出哪个顺序?
原因是事件是在冒泡阶段触发
但是当我们修改代码
big.onclick=function(e){
// console.log('我是big');
console.log(e.target);
}
// center.οnclick=function(){
// console.log('我是center');
// }
// small.οnclick=function(){
// console.log('我是small');
// }
此时结果是点击谁就输出谁
那么此时这个e.target是什么呢?它是我们事件捕获阶段最小的元素,虽然我们是给big绑定的事件,但是我点small,target就是small,点center就是center
此时再举一个例子:
<ul>
<li>苹果</li>
<li>香蕉</li>
<li>梨</li>
</ul>
let li=document.querySelectorAll('li')
let ul=document.querySelector('ul')
for(let i=0;i<li.length;i++){
li[i].onclick=function(){
ul.removeChild(this)
}
}
此时我们的需求是点击哪个水果就删除哪个
此时运行成功。
但是如果我们的页面文字特别多,每个元素都绑定事件的话,那我们需要绑定很多事件,那可能在效率,性能上都有很大的问题。并且如果我们新加进来元素仍然是没有办法删除的,此时我们可以利用事件委托实现这个功能。
let ul=document.querySelector('ul')
ul.onclick=function(e){
ul.removeChild(e.target)
}
此时,将子级的事件委托给父级来处理,大大简化了代码还实现了同一个功能。
综上:
- 事件委托: 给父元素注册事件,委托给子元素来处理
- 事件委托的原理: 事件冒泡
- 好处:
- 简化初始化并节省内存:无需添加许多处理程序。
- 更少的代码:添加或移除元素时,无需添加/移除处理程序。
- DOM 修改 :我们可以使用 innerHTML 等,来批量添加/移除元素。
- 事件委托也有其局限性:
- 首先,事件必须冒泡。而有些事件不会冒泡。此外,低级别的处理程序不应该使用event.stopPropagation()。
- 其次,委托可能会增加 CPU 负载,因为容器级别的处理程序会对容器中任意位置的事件做出反应,而不管我们是否对该事件感兴趣。但是,通常负载可以忽略不计,所以我们不考虑它。
- 使用事件委托需要三个步骤:
- 确定要监视事件的元素的父级元素
- 把将事件侦听器附加到父元素
- 用 event.target 选择目标元素