JavaScript 事件流模型及事件委托详解

JavaScript 中的事件流模型 事件冒泡事件捕获,以及 事件委托(也叫事件代理),是前端面试中常常出现的知识点,做为一名前端工程师,梳理基础知识点对你必定有所帮助。html

文章中全部的代码都有 codepen 实例,连接在对应的章节内,请同窗们尝试本身修改运行代码,以便加深理解。前端

1、名词解释

在开始讲解以前,咱们先熟悉几个概念node

事件

事件是能够被 JavaScript 侦测到的行为。
onclick onload onchange 等事件。面试

事件流

事件在页面中的响应顺序浏览器

事件流模型

为了更好的理解事件流模型,咱们把 DOM 树想象成一个靶子,父节点在外,子节点在内。以下图所示:性能优化

事件流模型 - 靶子

  • 事件冒泡(event bubbling) 由内向外,即从 DOM 树的子到父,div -> body -> html -> document
  • 事件捕获(event capturing) 由外向内,即从 DOM 树的父到子,document -> html -> body -> div

接下来咱们先经过代码实例详细讲解事件冒泡和事件捕获,而后讲解事件委托,并实现一个事件委托的实例。前端工程师

2、事件冒泡 vs. 事件捕获

代码地址: https://codepen.io/cecillia/p...

事件冒泡事件捕获 分别由 微软网景 公司提出,后来 W3C 将二者结合,平息了战火,制定了统一的标准 —— 先捕获再冒泡函数

addEventListener

在 JavaScript 中,addEventListener 方法用于向指定元素添加事件句柄。
语法:element.addEventListener(event, function, useCapture)性能

element 目标元素
event 事件名,如 click
function 事件触发时执行的函数
useCapture Bool值,true - 事件句柄在 捕获 阶段执行,false- false- 默认。事件句柄在 冒泡 阶段执行

事件冒泡

来看一段代码实例,思考运行后会弹出什么。优化

/**.html**/
<div class="t3">document
  <div class="t2">html
    <div class="t1">body
      <div class="t0">div</div>
    </div>
  </div>
</div>

/**.js**/
var $t0 = document.getElementsByClassName('t0')[0];
var $t1 = document.getElementsByClassName('t1')[0];
var $t2 = document.getElementsByClassName('t2')[0];
var $t3 = document.getElementsByClassName('t3')[0];

$t0.addEventListener("click", function(){
  alert("click div")
}, false);

$t1.addEventListener("click", function(){
  alert("click body")
}, false);

$t2.addEventListener("click", function(){
  alert("click html")
}, false);

$t3.addEventListener("click", function(){
  alert("click document")
}, false);

根据冒泡事件流模型由内向外的规则,会依次弹出:click div -> click body -> click html -> click docuement

事件捕获

将上一段代码中的 false 都改成 ture,则变为捕获方式:

/**.html**/
<div class="t3">document
  <div class="t2">html
    <div class="t1">body
      <div class="t0">div</div>
    </div>
  </div>
</div>

/**.js**/
var $t0 = document.getElementsByClassName('t0')[0];
var $t1 = document.getElementsByClassName('t1')[0];
var $t2 = document.getElementsByClassName('t2')[0];
var $t3 = document.getElementsByClassName('t3')[0];

$t0.addEventListener("click", function(){
  alert("click div")
}, true);

$t1.addEventListener("click", function(){
  alert("click body")
}, true);

$t2.addEventListener("click", function(){
  alert("click html")
}, true);

$t3.addEventListener("click", function(){
  alert("click document")
}, true);

根据捕获事件流模型由外向内的规则,会依次弹出:click document -> click html -> click body -> click div

事件冒泡&事件捕获同时存在

若是两种事件流模型同时存在会怎样展现呢?

/**.html**/
<div class="t3">document
  <div class="t2">html
    <div class="t1">body
      <div class="t0">div</div>
    </div>
  </div>
</div>

/**.js**/
var $t0 = document.getElementsByClassName('t0')[0];
var $t1 = document.getElementsByClassName('t1')[0];
var $t2 = document.getElementsByClassName('t2')[0];
var $t3 = document.getElementsByClassName('t3')[0];

$t0.addEventListener("click", function(){
  alert("click div")
}, false);

$t1.addEventListener("click", function(){
  alert("click body")
}, false);

$t2.addEventListener("click", function(){
  alert("click html")
}, true);

$t3.addEventListener("click", function(){
  alert("click document")
}, true);

原则:

  • 从外向内,捕获前进,遇到捕获事件当即执行
  • 非 target 节点,先捕获再冒泡
  • target 节点,按代码书写顺序执行(不管冒泡仍是捕获)

所以会依次弹出:click document -> click html -> click div -> click body

3、事件流模型的应用:事件委托

代码地址: https://codepen.io/cecillia/p...

事件委托 又叫 事件代理,指的是利用事件冒泡原理,只需给外层父容器添加事件,若内层子元素有点击事件,则会冒泡到父容器上,这就是事件委托,简单说就是:子元素委托它们的父级代为执行事件。

事件流模型在业务开发中有哪些应用场景呢?

例如,一个播放列表有成千上万首歌曲,若是遍历播放列表,给每一个 item 添加点击事件,而这样无疑会屡次访问 DOM,每次 DOM 操做都会引发浏览器的重绘与重排,很是不利于性能优化。

这时候咱们能够利用事件委托,只给最外层的容器添加响应事件,这样只需一次 DOM 操做,就能达到目的。

/**.html**/
<ul id="music">
  <li>青花瓷</li>
  <li>东风破</li>
  <li>双节棍</li>
</ul>

/**.js**/
var $music = document.getElementById('music');

$music.addEventListener('click', function(e) {
  if(e.target.nodeName.toLowerCase() === 'li') { // 判断目标元素target是否为li元素
    var content = e.target.innerHTML;
    console.log(content);
  }
}, false)

怎么样,事件委托也不过如此吧?只要掌握了事件冒泡、事件捕获的原理,并将其运用到实际业务开发中,就可以真正 get 事件委托这个知识点啦~


【欢迎指正,码字不易,喜欢请点赞哦】

相关文章
相关标签/搜索