一、简述DOM事件机制
DOM 事件标准描述了事件传播的 3 个阶段:
- 捕获阶段(Capturing phase)—— 事件(从 Window)向下走近元素。
- 目标阶段(Target phase)—— 事件到达目标元素。
- 冒泡阶段(Bubbling phase)—— 事件从元素上开始冒泡。
1.冒泡
当一个事件发生在一个元素上,它会首先运行在该元素上的处理程序,然后运行其父元素上的处理程序,然后一直向上到其他祖先上的处理程序。
2.event.target
父元素上的处理程序始终可以获取事件实际发生位置的详细信息。
引发事件的那个嵌套层级最深的元素被称为目标元素,可以通过 event.target 访问。
注意与 this(=event.currentTarget)之间的区别:
event.target—— 是引发事件的“目标”元素,它在冒泡过程中不会发生变化。this—— 是“当前”元素,其中有一个当前正在运行的处理程序。例如,如果我们有一个处理程序
form.onclick,那么它可以“捕获”表单内的所有点击。无论点击发生在哪>里,它都会冒泡到<form>并运行处理程序。在
form.onclick处理程序中:
this(=event.currentTarget)是<form>元素,因为处理程序在它上面运行。event.target是表单中实际被点击的元素。 案例见:target示例
3.停止冒泡
冒泡事件从目标元素开始向上冒泡。通常,它会一直上升到
<html>,然后再到document对象,有些事件甚至会到达window,它们会调用路径上所有的处理程序。但是任意处理程序都可以决定事件已经被完全处理,并停止冒泡。
用于停止冒泡的方法是
event.stopPropagation()。
4.捕获
事件处理的另一个阶段被称为“捕获(capturing)”。它很少被用在实际开发中,但有时是有用的。
DOM 事件标准描述了事件传播的 3 个阶段:
- 捕获阶段(Capturing phase)—— 事件(从 Window)向下走近元素。
- 目标阶段(Target phase)—— 事件到达目标元素。
- 冒泡阶段(Bubbling phase)—— 事件从元素上开始冒泡 下面是在表格中点击
<td>的图片:
也就是说:点击 <td>,事件首先通过祖先链向下到达元素(捕获阶段),然后到达目标(目标阶段),最后上升(冒泡阶段),在途中调用处理程序。
使用 on<event> 属性或使用 HTML 特性(attribute)或使用两个参数的 addEventListener(event, handler) 添加的处理程序,对捕获一无所知,它们仅在第二阶段和第三阶段运行。
请注意,虽然形式上有 3 个阶段,但第 2 阶段(“目标阶段”:事件到达元素)没有被单独处理:捕获阶段和冒泡阶段的处理程序都在该阶段被触发。
案例:
捕获和冒泡示例
注意:目标阶段会被执行两次。
二、事件委托
事件代理又叫事件委托,JavaScript高级程序设计上讲:事件委托就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。
为什么要用事件委托:
-
减少内存消耗,提高性能
-
动态监听元素 场景: 假如有一个
<table>,里面有多个<td>,我们的任务是在点击时高亮显示被点击的单元格<td>。 -
假如在每一个
<td>上添加监听事件,这样不仅会浪费内存(监听器数量增多),而且添加新的<td>时,还需要绑定事件,不够灵活。 -
而我们使用事件委托,可以在
<td>的共同祖先<table>元素上设置一个“捕获所有”的处理程序。则很好的解决了这两个问题。
详情见:事件委托