DOM事宜流与事宜托付

事宜流与事宜托付

事宜,即文档或浏览器中发作的一些特定交互的霎时,我们能够应用事宜监听来预定事宜,当事宜发作的时刻实行相应的处置惩罚递次。当事宜发作在某个DOM节点上时,事宜在DOM构造中举行一级一级的通报,这便形成了“流”,事宜流便形貌了从页面中吸收事宜的递次。本文重要议论事宜流的三个阶段,及应用事宜托付机制举行机能优化。

DOM事宜流

关于事宜流的明白,《JS高程三》中有个抽象的比方:

能够设想画在一张纸上的一组同心圆,假如你把手指放在圆心上,那末你的手指指向的实在不是一个圆,而是纸上一切的圆。…>换句话说,在单击按钮的同时,你也单击了按钮的容器元素,以至也单击了全部页面。

————《JavaScript高等递次设计(第三版)》page 345

DOM2级事宜中划定事宜流包括3个阶段:

  • 捕捉阶段

  • 处于目的阶段

  • 冒泡阶段

起首发作的是事宜捕捉阶段,此时事宜还没有通报到目的节点对象上,所以我们就有时机在这个阶段举行事宜的截。然后是目的节点吸收到事宜,末了是事宜冒泡阶段,能够在这个阶段对事宜做出处置惩罚和相应。
我们先定义一段简朴的html构造:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
  </head>
  <body>
      <div class="box">
          <button type="button" name="button">click me</button>
      </div>
  </body>
</html>

事宜捕捉阶段

在事宜捕捉阶段中,先由不详细的节点(即上层节点)吸收到事宜,然后一级一级往下通报,直到最详细的目的节点吸收到事宜。
在DOM2级事宜范例中,请求事宜从document对象最先通报,然则诸如Chrome,Firefox等主流浏览器倒是从window最先通报的。

addEventListener要领的第三个参数是一个布尔值(可选),指定事宜处置惩罚递次是不是在捕捉或冒泡阶段实行。 当为true时,则事宜处置惩罚递次将在捕捉阶段实行。

误区:不管addEventListener的第三个参数是不是为true,三个阶段都邑走一遍,这里的第三个参数,指的是处置惩罚递次将会在捕捉或许冒泡阶段实行,好比是你想买菜,你能够在上班路上,或许放工路上完成买菜,但不管什么时刻买菜,你都要把这两段旅程走完。

document.querySelector('#btn').addEventListener('click', function () {
    console.log("btn was clicked");
},true);

document.querySelector('body').addEventListener('click', function () {
    console.log("body was clicked");
},true);

document.querySelector('.box').addEventListener('click', function () {
    console.log("box was clicked");
},true);

document.addEventListener('click', function () {
    console.log("document was clicked");
},true);

window.addEventListener('click', function () {
    console.log("window was clicked");
},true);

点击click me按钮后,控制台顺次打印出实行效果:

window was clicked
document was clicked
body was clicked
box was clikced
btn was clicked

很明显能够看出,在捕捉阶段,事宜由window对象最先,一级一级地向下通报,直到通报到最详细的button对象上。

事宜冒泡阶段

事宜冒泡阶段与捕捉阶段恰好相反,冒泡阶段是从最详细的目的对象最先,一层一层地向上通报,直到window对象。
addEventListener要领默许就是从冒泡阶段实行事宜处置惩罚递次。

document.querySelector('#btn').addEventListener('click', function () {
    console.log("btn was clicked");
});

document.querySelector('body').addEventListener('click', function () {
    console.log("body was clicked");
});

document.querySelector('.box').addEventListener('click', function () {
    console.log("box was clicked");
});

document.addEventListener('click', function () {
    console.log("document was clicked");
});

window.addEventListener('click', function () {
    console.log("window was clicked");
});

点击click me按钮后,控制台顺次打印出实行效果:

btn was clicked
box was clikced
body was clicked
document was clicked
window was clicked

上述历程示意图:
《DOM事宜流与事宜托付》

阻挠事宜冒泡

我们能够运用event.stopPropagation()要领阻挠事宜冒泡历程,以防备事宜冒泡而带来不必要的毛病和搅扰。
示例:

document.querySelector('#btn').addEventListener('click', function (event) {
    console.log("btn was clicked");
    event.stopPropagation();
});

document.querySelector('body').addEventListener('click', function () {
    console.log("body was clicked");
});

document.querySelector('.box').addEventListener('click', function () {
    console.log("box was clicked");
});

document.addEventListener('click', function () {
    console.log("document was clicked");
});

window.addEventListener('click', function () {
    console.log("window was clicked");
});

点击click me按钮后,控制台打印出实行效果显现,事宜没有再向上冒泡通报给其他节点对象:

btn was clicked

事宜托付

每一个函数都是对象,都邑占用内存,所以当我们的页面中所包括的事宜数目较多时,假如给每一个节点绑定一个事宜,加上事宜处置惩罚递次,就会形成机能很差。另有一个题目是,某个元素节点是厥后经由过程JavaScript动态添加进页面中的,这时刻我们假如提早对它举行绑定,但此时该元素并不存在,所以会绑定事宜会失利。处理上述两个题目的一个经常使用计划,就是运用事宜托付
举例来说:

document.querySelector('.box').addEventListener(function (event) {
    switch (event.target.id) {
      case "btn":
        console.log("btn was clicked");
        break;
      case "btn-2":
        console.log("btn-2 was clicked");
        break;
      default:
        console.log("box was clicked");
        break;
    }
});
$(".box").append("<button id='btn-2'>btn-2</button>");

简朴说,事宜托付就是把原本该本身吸收的事宜托付给本身的上级(父级,祖父级等等)的某个节点,让本身的“尊长们”帮助盯着,一旦有事宜触发,再由“尊长们”通知本身:“喂,孙子,有人找你~~”。
恩,差不多就是这么个意义,可怜天下父母心。

程度有限,迎接人人不吝指正。

    原文作者:司楠
    原文地址: https://segmentfault.com/a/1190000007009451
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞