定义
事件传播 (Event Propagation)
事件在 DOM 树中的传递.
事件捕获 (Event Capturing)
事件在 DOM 树中由顶至底的传递和响应.
事件冒泡 (Event Bubbling)
事件在 DOM 树中由底至顶的传递和响应.
事件绑定 (Event Listening)
添加事件绑定的方法:
1. 在 DOM 元素中绑定
<div id="root" onclick="someEventHandler()"></div>
2. js 元素直接绑定
document.getElementById('root').onclick = function(e) {
someEventHandler(e)
};
3. js 事件绑定函数
let root = document.getElementById('root');
root.addEventListener('click', function(e) {
someEventHandler(e);
}, false);
Event Reference: Event Reference
第 3 个参数可选, 决定是否捕获事件, 默认为否, 即不捕获事件 (即冒泡) .
详见: EventTarget.addEventListener().
事件流 (Event Flow)
流向
事件流的原则很简单: 先捕获再冒泡.
对以下 DOM 元素:
<div id="root">
<div id="branch">
<div id="div-a"></div>
<div id="div-b"></div>
</div>
</div>
当全部绑定冒泡事件 (以点击 (click) 为例) 时, 事件由事件发生的最底层子元素开始传播, 并由底至顶向上冒泡, 所以:
点击 "div-a" 元素, 触发响应: "div-a" -> "branch" -> "root"
当全部绑定捕获事件时, 事件由最顶层元素开始传播, 并由顶至底向下捕获, 所以:
点击 "div-a" 元素, 触发响应: "root" -> "branch" -> "div-a"
具体来说:
let root = document.getElementById('root');
let branch = document.getElementById('branch');
let divA = document.getElementById('div-a');
let divB = document.getElementById('div-b');
root.addEventListener('click', function (e) {
console.log('js: root 捕获');
}, true);
branch.addEventListener('click', function (e) {
// e.stopPropagation();
console.log('js: branch 捕获');
}, true);
divA.addEventListener('click', function (e) {
console.log('js: divA 捕获');
}, true);
divB.addEventListener('click', function (e) {
console.log('js: divB 捕获');
}, true);
root.addEventListener('click', function (e) {
console.log('js: root 冒泡');
});
branch.addEventListener('click', function (e) {
console.log('js: branch 冒泡');
});
divA.addEventListener('click', function (e) {
console.log('js: divA 冒泡');
});
divB.addEventListener('click', function (e) {
console.log('js: divB 冒泡');
});
点击 "div-a" 元素, 控制台内容:
js: root 捕获
js: branch 捕获
js: divA 捕获
js: divA 冒泡
js: branch 冒泡
js: root 冒泡
事件流控制
停止事件传播: event.stopPropagation
, 如果把上例唯一的一个注释取消, 再点击 "div-a" 元素将使得控制台输出变为:
js: root 捕获
js: branch 捕获
因为在 "branch" 元素捕获事件后, 就停止了该事件的传播.
有的元素, 如 <a> 元素, 绑定有默认事件 (跳转链接) , 这时候可以用 event.preventDefault()
方法阻止默认事件, 这在用 js 代理事件时非常有用.
获取事件响应对象
在事件处理函数中有两个语句获取事件响应对象: event.target
和 event.currentTarget
, 区别在于, event.target
始终指向事件发生的真实元素, 如前例中的 "div-a" , 而 event.currentTarget
则指向当前的事件响应对象, 即, 可能是 "div-a", 也可能是 "branch" 和 "root" .
如果直接用匿名方法处理事件, 则 event.currentTarget
指向的对象和 this
是相同的.
REFERENCE: