Javascript——浅谈 Event Flow

1、Javascript Events : Event Bubbling(事件冒泡)

如果事件从最特定的元素开始,则事件流中的一个阶段称为事件冒泡(DOM中可能最深的节点)然后向上流向最不特定的节点(i.e 电子文档)

当元素<div>被单击时,单击事件按以下顺序发生(参见上图):

  1. <div>
  2. <body>
  3. <html>
  4. Document

事件单击首先在元素(元素单击)上启动。然后它向上移动DOM树,沿着它的路径向每个节点开火,直到它到达文档对象。


 

2、Javascript Events : Event Capturing(事件捕获)

 

另一种事件流模型称为事件捕获,它首先由Netscape浏览器引入。

根据该模型,最不特定的节点首先接收事件,最特定的节点最后接收事件。

它的设计目的是在事件到达目标之前拦截它

参考前面的示例,单击元素按以下顺序触发单击事件。

  1. Document
  2. <body>
  3. <html>
  4. <div>

事件捕获在现代浏览器中缺乏浏览器支持,因此用户必须在特殊情况下使用事件捕获时自由使用冒泡。


3、Javascript Events : DOM Event Flow(DOM 事件流)

DOM Level 2事件指定的事件流模型有三个阶段:

  • Event Capturing Phase
  • At the target
  • Event Bubbling Phase.

首先发生事件捕获,前提是存在拦截事件的机会。

然后实际目标获取事件。

然后进入冒泡的最后阶段,允许对事件做出最终响应。

参考前面的示例,单击元素按上面图中指定的顺序触发事件。


4、Javascript Events : The Capturing Phase(捕获阶段)

DOM Level 2事件定义的事件流有三个阶段:捕获阶段、目标阶段和事件冒泡阶段。

首先是事件捕获,它提供了一个在必要时拦截事件的机会。

然后实际目标接收事件。

最后一个阶段是冒泡,允许对事件进行响应。

示例:用于事件处理的Javascript DOM。

注意:使用throwIt()函数来代替多重if语句。


5、JS事件流原理图/process(过程)如下:

从图中我们可以知道:

1、一个完整的JS事件流是从window开始,最后回到window的一个过程。

2、事件流被分为三个阶段(1~5)捕获过程、(5~6)目标过程、(6~10)冒泡过程。

3、在冒泡过程中6比7早触发,也就解释了上面那题,为什么btn1,会比content先触发。

然而在有些情况下JS的事件流不会根据上图这个从捕获过程到目标过程到冒泡过程这样去推进的。

从表中我们可以知道在DOM Level 0事件的时候是不支持捕获事件的。


 

6、事件的属性及方法

  • bubbles: 布尔值,表示事件是否冒泡
  • cancelable: 布尔值,表示是否可以取消事件的默认行为
  • currentTarget: 元素,事件处理程序当前正在处理事件的那个元素
  • defaultPrevented: 布尔值,表示是否调用过preventDefault()方法
  • detail: 整数,与事件相关的细节信息
  • eventPhase: 整数,调用事件处理程序的阶段,1表示捕获阶段,2表示目标阶段,3表示冒泡阶段
  • preventDefault(): 函数,取消事件的默认行为,cancelable为true时可以调用该方法
  • stopImmediatePropagation(): 函数,取消事件的进一步捕获或冒泡,同时阻止任何事件处理程序被调用
  • stopPropagation(): 函数,取消事件的进一步捕获或冒泡,bubbles为true时可以调用这个方法
  • target: 元素,事件的目标
  • trusted: 布尔值,为true时表示事件是浏览器生成的,否则表示事件是通过JS创建的
  • type: 字符串,被触发的事件类型
  • view: 与事件关联的抽象视图,等同于发生事件的window对象

下面代码示例展示了上述部分属性的用法,也可以帮助我们进一步理解事件流。假设页面中有一个按钮”myBtn”。当点击按钮时,this和currentTarget都等于body元素,因为事件处理程序是注册在body元素上。target的值却等于按钮元素,因为它是click事件的真正目标。由于按钮上没有注册事件处理程序,结果”click”事件冒泡到了document.body那里才得到处理。

document.body.onclick = function(event) {
 console.log(event.currentTarget === document.body); // true
 console.log(this === document.body); // true
 console.log(event.target === document.getElementById("myBtn")); // true
};

再看一个例子,下面代码中,stopPropagation()方法取消了事件的进一步捕获或冒泡。当我点击按钮时,本来应该会因为事件冒泡机制触发按钮和body元素上的点击事件处理程序,输出”From Bth …”和”From Body …”。现在点击事件在按钮元素上触发之后就被阻止继续在DOM层次中的传播,因此body上的事件处理程序不会被触发。

document.body.onclick = function(event) {
 console.log(event.currentTarget === document.body); // true
 console.log(this === document.body); // true
 console.log(event.target === document.getElementById("myBtn")); // true
};

7、Javascript Events: Event Listeners(事件监听器)

DOM Level 2事件定义了两个用于分配和删除事件处理程序的方法:addeventlistener()和removeeventlistener ()。

这些方法存在于所有DOM节点上,并接受三个参数:要处理的事件名称、事件处理函数和表示是否调用事件处理程序i的布尔值。i.e 真与假。

事件监听器有一个类似于事件处理程序的函数,不同的是,在将多个函数分配给同一个DOM元素和事件时,处理程序没有限制。

在下面的演示中,脚本使用addEventListener方法将handleMouseOver和handleMouseOut函数注册为元素p的事件处理程序,其id值为content。

但是当您单击按钮时,方法removeEventListener将handleMouseOut函数与元素p分离。

示例:Javascript DOM:使用内联事件处理事件

注意:onclick属性用于设置用于单击事件的处理程序。

 

posted @ 2018-11-11 20:30  温柔の风  阅读(185)  评论(0编辑  收藏