事件冒泡与事件捕获
2020 javascript事件流描述的是从页面中接受事件的顺序,主要是事件冒泡和事件捕获。
事件冒泡
事件冒泡(event bubbling),即事件开始时由最具体的元素接收,然后逐级向上传播到 window 对象。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Document</title>
</head>
<body>
<div id="myDiv">Click</div>
</body>
</html>
当点击了 div 元素,事件传播 div -> body -> html -> Document -> window。
事件捕获
事件捕获(event capturing),是由事件从 window 对象开始接收事件,然后逐级向下传播到具体元素。
如上代码,点击掉了 div 元素,事件传播 window -> Document -> html -> body -> div。
DOM 事件流
三个阶段:事件捕获阶段,处于目标阶段和事件冒泡阶段。
新增事件和删除事件的操作:addEventListener(type, listener [, options])
和 removeEventListener(type, listener [, options])
事件委托
事件委托就是利用事件的冒泡原理,把元素的响应事件代理到其父辈元素上,可以减少循环绑定。
<!-- 普通的html列表标签 -->
<ul id="list">
<li>item 1</li>
<li>item 2</li>
<li>item 3</li>
</ul>
/* 普通的遍历元素注册事件监听 */
var items = document.getElementsByTagName('li');
for (var i = 0; i < items.length; i++) {
items[i].addEventListener('click', function (e) {
e.target.parentNode.removeChild(e.target);
});
}
/* 事件委托 */
var list = document.getElementById('list');
list.addEventListener('click', function (e) {
list.removeChild(e.target);
});
event 对象的属性和方法
属性/方法 | 类型 | 说明 |
---|---|---|
target | Element | 事件的目标 |
currentTarget | Element | 其事件处理程序当前正在处理事件的那么元素,即触发事件的元素 |
preventDefault | Function | 取消事件的默认行为 |
stopPropagation | Function | 取消事件的进一步捕获或冒泡 |
target 与 currentTarget
<div class="container">
<button>Click me</button>
</div>
const div = document.querySelector('.container');
div.addEventListener('click', (e) => {
console.log('target', e.target);
console.log('currentTarget', e.currentTarget);
});
当我们点击按钮的时候,我们可以看到不同的输出结果
target <button>Click me</button>
currentTarget <div class="container">...</div>
- targt 是触发事件的根元素
- currentTarget 是处理该事件的元素
不会触发冒泡的事件
- scroll
- blur
- focus
- mouseentter
- mouseleave
其他
React 的事件体系就是基于事件委托建立的,其中有很大的部分都是处理不同事件之间的差异性的,对于这些不会冒泡的事件,React 也进行了处理。
React 的事件系统可以参考上一篇的《React事件系统》
参考链接
- 《JavaScript 高级程序设计(第 3 版)》
- React 中的事件委托
- Event target v currentTarget