【前置知识】
- 事件捕获
- 事件冒泡
什么是事件委托
捕获和冒泡允许我们实现一种被称为 事件委托 的强大的事件处理模式。
思路
如果我们有许多以类似方式处理的元素,那么就不必为每个元素分配一个处理程序 —— 而是将单个处理程序放在它们的共同祖先上。
如图

该表格有9个格子,想要实现点击时高亮显示被点击的单元格 。
代码大概如下
<table><tr><td class="a1">1</td><td class="a2">2</td><td class="a3">3</td></tr><tr><td class="a4">4</td><td class="a5">5</td><td class="a6">6</td></tr><tr><td class="a7">7</td><td class="a8">8</td><td class="a9">9</td></tr></table>
效率低下的做法: 为每个 <td> (可能更多)分配一个 onclick
~~
事件委托做法:直接在 <table> 设置一个“捕获所有”的处理程序。
let selectedTd;let table = document.getElementsByTagName('table');let highlight = (td) => {if(selectedTd) {// 移除现有的高亮显示,如果有的话selectedTd.classList.remove('highlight')}selectedTd = td;selectedTd.classList.add('highlight');}table.onclick = (event) => {let target = event.target; //在哪里点击?if(target.tagName != 'TD') return;highlight(target)}
什么是事件委托
- 事件委托指的是不在事件的发生地(直接DOM)上设置监听函数,而是在其父元素上设置监听函数。
- 通过事件冒泡,父元素可以监听到被触发的子元素事件,通过判断事件发生元素DOM的类型,来作出不同的响应。
- 当子元素有很多时,使用事件委托可以避免对特定的每个节点添加事件监听器,事件监听被添加到它们的父元素上,事件监听函数这是可以从子元素上冒泡上来的事件,找到是哪个子元素事件。
怎么阻止默认动作
默认动作指的是什么?
默认动作指的是浏览器自己的行为。
例如:
- 点击
<a href="#">的时候浏览器自动跳转到指定页面。 - 滚动鼠标时页面会向下滚动,但我们按空格键和按方向键时页面也会向下滚动。
- 等等
有时候有一些需求,为了更好的用户体验,需要阻止浏览器本身的默认行动。
办法
有两种方式:
- 主流的方法是使用
event对象,有一个event.preventDefault()方法。 - 如果处理程序是使用
on<event>(而不是addEventListener)分配的,那返回false也同样有效。
<a href="/" onclick="return false">Click here</a>//or<a href="/" onclick="event.preventDefault()">Click here</a>
怎么阻止事件冒泡
例子:
<div class="爷爷"><div class="爸爸"><div class="儿子">文字</div></div></div>
如上代码,假如我分别给爷爷、爸爸、儿子绑定 fnYe 、 fnBa 、 fnEr 三种点击事件。
- 如果我没有阻止默认事件,则默认会按下面执行:
- 当我点击
文字时,就会按照事件捕获从Window—>Document—><html>—><body>—><div class="爷爷">—><div class="爸爸">—><div class="儿子">寻找是否有监听。 - 然后,就会按照冒泡事件从
<div class="儿子">一直到Window的过程寻找是否有监听,并依次执行监听,事件捕获是相反的。

:::info
趣事:
IE5支持事件冒泡,而网景支持事件捕获。因为意见不合这两家公司闹到w3c。然后为了让这两家公司觉得公平,就规定浏览器应该同时支持两种调用顺序。
:::
如何阻止事件冒泡?
冒泡事件如同冒泡一样,从底部上升到水面,这个上升的过程还会依次执行代码,例如上面的儿子爸爸爷爷的代码,如图
默认情况下,当我点击 儿子 时,就会依次执行fuer 、 fuba 和fuye ,
如果我只想执行 fuer ,不想执行 后面的fuba 和 fuye ,就需要阻止冒泡事件。
两种方法:
event.stopPropagation(); //W3C//orevent.cancelBubble = true; //IE
虽然不太可能遇到,但如果需要兼容IE,可以这样:
if (document.all) {// IEevent.cancelBubble = true;} else {event.stopPropagation();}
【资料来源】 事件委托—-javascript.info 冒泡和捕获—-JavaScript.info 浏览器默认行为—-JavaScript.info
