24 Feb 2017 10:08 +0000

定义

事件传播 (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>
"root"
"branch"
"div-a"
"div-b"

当全部绑定冒泡事件 (以点击 (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.targetevent.currentTarget , 区别在于, event.target 始终指向事件发生的真实元素, 如前例中的 "div-a" , 而 event.currentTarget 则指向当前的事件响应对象, 即, 可能是 "div-a", 也可能是 "branch" 和 "root" .

如果直接用匿名方法处理事件, 则 event.currentTarget 指向的对象和 this 是相同的.

 


REFERENCE:

EventTarget.addEventListener() - MDN

JavaScript 详说事件机制之冒泡、捕获、传播、委托

Browser events: bubbling, capturing, and delegation


Loading comments...