浏览器的事件流

定义

	浏览器的事件流是指在浏览器中,从页面中接收事件(onKeyDown, onKeyMove)的顺序,

DOM事件流三个阶段

事件冒泡 和 事件捕获 分别由 微软 和 网景 公司提出,后来 W3C 将两者结合,平息了战火,制定了统一的标准 —— 先捕获再冒泡。)由内向外
在这里插入图片描述
下面通过几个例子讲解DOM事件流的三个阶段

1、事件捕获阶段

由外向内,即从 DOM 树的父到子,document -> html -> body -> div

<!DOCTYPE html>
<html>
  <body>
    <button id="myButton">点击按钮</button>
  </body>
  <script>
    document.getElementById('myButton').addEventListener(
      'click',
      function(ev) {
        alert(1);
      },
      false
    );
    document.body.addEventListener(
      'click',
      function(ev) {
        alert(2);
      },
      false
    );
    document.addEventListener(
      'click',
      function(ev) {
        alert(3);
      },
      false
    );
  </script>
</html>

addEventListener() 为DOM2级事件处理程序,它接受三个参数:要处理的事件名、作为事件处理程序的函数和一个布尔值。最后这个布尔值参数如果是 true,表示在捕获 阶段调用事件处理程序;如果是 false,表示在冒泡阶段调用事件处理程序。
上面代码中会先后弹出3次alter弹窗,顺序分别为1、2、3。也就是说,click事件首先在

元素上发生,而这个元素就是我们单击的元素。然后,click 事件沿DOM树向上传播,在每一级节点上都会发生,直至传播到document对象。

2、目标阶段
3、事件冒泡阶段

即从 DOM 树的子到父,div -> body -> html -> document

<!DOCTYPE html>
<html>
  <body>
    <button id="myButton">点击按钮</button>
  </body>
  <script>
    document.getElementById('myButton').addEventListener(
      'click',
      function(ev) {
        alert(1);
      },
      true
    );
    document.body.addEventListener(
      'click',
      function(ev) {
        alert(2);
      },
      true
    );
    document.addEventListener(
      'click',
      function(ev) {
        alert(3);
      },
      true
    );
  </script>
</html>

上面代码中会先后弹出3、2、1的结果,和事件冒泡完全相反。

<!DOCTYPE html>
<html>
  <body>
    <button id="myButton">点击按钮</button>
  </body>
  <script>
    // 冒泡阶段处理
    document.getElementById('myButton').addEventListener(
      'click',
      function(ev) {
        alert(1);
      },
      false
    );
    // 捕获阶段处理
    document.body.addEventListener(
      'click',
      function(ev) {
        alert(2);
      },
      true
    );
    // 冒泡阶段处理
    document.addEventListener(
      'click',
      function(ev) {
        alert(3);
      },
      false
    );
  </script>
</html>

在代码中,把元素的点击事件处理放在了捕获阶段,而把和document的点击事件处理放在了冒泡阶段,按照DOM事件流事件的传播顺序为

(1) body

(2) button

(3) document

所以最终的弹出结果为 2、1、3。

<!DOCTYPE html>
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div id="div1">
        <button id="btn">按钮</button>
    </div>
<script>
    var btn = document.getElementById("btn");
    var div1 = document.getElementById("div1");

    //事件冒泡
    btn.onclick = function(){
        console.debug("冒泡1.Click btn");
    }
    div1.onclick = function(){
        console.debug("冒泡1.5 Click div1");
    }
    document.body.onclick = function(){
        console.debug("冒泡2.Click Body");
    }
    document.onclick = function(){
        console.debug("冒泡3.Click document");
    }
    window.onclick = function(){
        console.debug("冒泡4.Click window");
    }

    //事件捕获
    window.addEventListener("click",function(){
        console.debug("捕获4.Click window");
    },true);
    document.addEventListener("click",function(){
        console.debug("捕获3.Click document");
    },true);
    document.body.addEventListener("click",function(){
        console.debug("捕获2.Click body");
    },true);
    div1.addEventListener("click",function(){
        console.debug("捕获1.5 Click div1");
    },true);
    btn.addEventListener("click",function(){
        console.debug("捕获1.Click btn");
    },true);
</script>

</body>
</html>

Chrome console 结果
在这里插入图片描述
疑问:图中『冒泡 1』与『捕获 1』的顺序为什么是反的?
事件传播三阶段:
capture phase(事件捕获)
target phase(处于目标)
bubbling phase(事件冒泡)
在 target phase,event handler 被调用的顺序不再遵循先捕获,后冒泡的原则,而是严格按照 event handler 注册的顺序
在例子中,

btn.onclick = function(){
console.debug(“冒泡1.Click btn”);
}
先于

btn.addEventListener(“click”,function(){
console.debug(“捕获1.Click btn”);
},true);
注册,故而先执行。

要改变二者的执行顺序,只需要改变两段源码的顺序即可。

W3C 规范:

Next, the implementation must determine the current target’s candidate event listeners. This must be the list of all event listeners that have been registered on the current target in their order of registration. [HTML5] defines the ordering of listeners registered through event handler attributes. Once determined, the candidate event listeners must not be changed. Adding or removing listeners does not affect the current target’s candidate event listeners.
``

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值