zoukankan      html  css  js  c++  java
  • 事件冒泡

    事件冒泡

     一.事件流概念

    流是一种生动体现。用术语说流是对输入输出设备的抽象。以程序的角度说,流是具有方向的数据。

    事件流分事件冒泡与事件捕获

    在浏览器发展的过程中,开发团队遇到了一个问题。那就是页面中的哪一部分拥有特定的事件?

    可以想象画在一张纸上的一组同心圆,如果你把手指放在圆心上,那么你的手指指向的其实不是一个圆,而是纸上所有的圆。放到实际页面中就是,你点击一个按钮,事实上你还同时点击了按钮所有的父元素。
    开发团队的问题就在于,当点击按钮时,是按钮最外层的父元素先收到事件并执行,还是具体元素先收到事件并执行?所以这儿引入了事件流的概念。

    通俗说,事件流所描述的就是从页面中接受事件的顺序。

    因为有两种观点,所以事件流也有两种,分别是事件冒泡和事件捕获。现主流是事件冒泡。

    事件冒泡

    事件冒泡即事件开始时,由最具体的元素接收(也就是事件发生所在的节点),然后逐级传播到较为不具体的节点。

    下面写个例子:

    复制代码
     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4   <meta charset="UTF-8">
     5   <title>Event Bubbling</title>
     6 </head>
     7 <body>
     8   <button id="clickMe">Click Me</button>
     9 </body>
    10 </html>
    复制代码

    然后,我们给button和它的父元素,加入点击事件。

    复制代码
     1 var button = document.getElementById('clickMe');
     2 
     3 button.onclick = function() {
     4   console.log('1. You click Button');
     5 };
     6 document.body.onclick = function() {
     7   console.log('2. You click body');
     8 };
     9 document.onclick = function() {
    10   console.log('3. You click document');
    11 };
    12 window.onclick = function() {
    13   console.log('4. You click window');
    14 };
    复制代码

    在Chrome浏览器运行:

    如果点击了button,那么这个点击事件会按如下的顺序传播

    1. button
    2. body
    3. document
    4. window

    也就是说,click事件首先在<button>元素上发生,然后逐级向上传播。

     

    事件捕获

    事件捕获的概念,与事件冒泡正好相反。它认为当某个事件发生时,父元素应该更早接收到事件,具体元素则最后接收到事件。比如说刚才的demo,如果是事件捕获的话,事件发生顺序会是这样的:

    1. window
    2. document
    3. body
    4. button

    事件阶段(Event Phases)

    当一个DOM事件触发时,它不是在触发的对象上只触发一次的,而是经历三个阶段。分别为

    1:一开始从文档的根节点流向目标对象(捕获阶段)

    2:然后在目标对向上被触发(目标阶段)

    3:之后再回溯到文档的根节点(冒泡阶段).

    1. 事件捕获阶段

    事件的第一个阶段是捕获阶段。事件从文档的根节点出发,随着DOM树的结构向事件的目标节点流去。途中经过各个层次的DOM节点,并在各节点上触发捕获事件,直到到达事件的目标节点。捕获阶段的主要任务是建立传播路径,在冒泡阶段,事件会通过这个路径回溯到文档跟节点。当事件发生时,首先发生的是事件捕获,为父元素截获事件提供了机会。
    例如,我把上面的Demo中,window点击事件更改为使用事件捕获模式。(addEventListener最后一个参数,true则代表使用事件捕获模式,false则表示使用事件冒泡模式。不理解的可以去学习一下addEventListener函数的使用)

    1 window.addEventListener('click', function() {
    2   console.log('4. You click window');
    3 }, true);

    此时,点击button的效果是这样的。

    可以看到,点击事件先被父元素截获了,且该函数只在事件捕获阶段起作用。

     

    处于目标与事件冒泡阶段

    事件到了具体元素时,在具体元素上发生,并且被看成冒泡阶段的一部分。
    随后,冒泡阶段发生,事件开始冒泡。

     

    阻止事件冒泡

    事件冒泡过程,是可以被阻止的。防止事件冒泡而带来不必要的错误和困扰。
    这个方法就是:stopPropagation()
    我们对button的click事件做一些改造。

    1 button.addEventListener('click', function(event) {
    2   // event为事件对象
    3   console.log('1. You click Button');
    4   event.stopPropagation();
    5   console.log('Stop Propagation!');
    6 }, false);

     点击后,效果如下图:

    不难看出,事件在到达具体元素后,停止了冒泡。但不影响父元素的事件捕获。

     

    总结

    事件流:描述的就是从页面中接受事件的顺序。

    分有事件冒泡与事件捕获两种。


    DOM事件流的三个阶段:

      1. 事件捕获阶段
      2. 处于目标阶段
      3. 事件冒泡阶段

     

    转载于刘彦佐“面试整理之DOM事件阶段”一文

     

     

  • 相关阅读:
    LeetCode 811. Subdomain Visit Count (子域名访问计数)
    LeetCode 884. Uncommon Words from Two Sentences (两句话中的不常见单词)
    LeetCode 939. Minimum Area Rectangle (最小面积矩形)
    LeetCode 781. Rabbits in Forest (森林中的兔子)
    LeetCode 739. Daily Temperatures (每日温度)
    三种方式实现按钮的点击事件
    239. Sliding Window Maximum
    14.TCP的坚持定时器和保活定时器
    13.TCP的超时与重传
    12.TCP的成块数据流
  • 原文地址:https://www.cnblogs.com/hewasdrunk/p/7380837.html
Copyright © 2011-2022 走看看