整理之DOM事件阶段、冒泡与捕获、事件委托、ie事件和dom模型事件、鼠标事件

整理之DOM事件阶段

本文主要解决的问题:

  1. 事件流
  2. DOM事件流的三个阶段

先理解流的概念

在现今的JavaScript中随处可见。比如说React中的单向数据流,Node中的流,又或是今天本文所讲的DOM事件流。都是流的一种生动体现。用术语说流是对输入输出设备的抽象。以程序的角度说,流是具有方向的数据。

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

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

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

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

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

事件冒泡

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

下面写个例子:

 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. 事件冒泡阶段

参考资料:《JavaScript高级程序设计》第三版


冒泡与捕获、事件委托、ie事件和dom模型事件、鼠标事件

一直没有搞懂jquery中的事件是怎么添加事件处理程序的。原来就是用了事件委托,关键就是通过冒泡方式实现在最高层(document)处理事件,通过判断事件target的id,给以不同的handler。当然也可以通过事件捕获来处理,但是因为ie中只有冒泡,所以还是用冒泡兼容性更好一些。

细细总结一下:

1.冒泡与捕获。

冒泡和捕获是两个完全不同的事件流传播方式,当点击页面上某个元素时,不知道用户是对该元素感兴趣还是对该元素的父元素该兴趣?为此提出了两种不同的事件流模型。一种是捕获,由网景提出的,首先是最不具体的元素接收到事件,然后再一级一级传播到最具体的元素。另一种是冒泡,是由ie提出的,它和捕获完全相反,首先是最具体的元素接收到事件,然后一级一级传播到最不具体的元素,一般都是document。

2.事件委托

上面的参考博文写得很清楚了。大概模式就是这样(以onclick为例子,其他事件mouseover mousemove mouseout mousedown mouseup click dbclick keyup keydown)

document.onclick=function(event){

var event=event?event:window.event;

var target=event.target?event.target:event.srcElement;

switch(target.id){

  case:‘btnid1‘:

  btnid1handler();

  break;

  case:‘btnid2‘:

  btnid2handler();

  break;

  }

};

3.ie事件和dom(2)事件模型

ie事件模型的事件流只包括事件冒泡,而dom(2)事件模型的事件流包括三个阶段:事件捕获阶段,处于目标阶段和事件冒泡阶段。ie8以下的版本只支持ie事件模型,ie9及其他浏览器都支持dom事件流。

区别:

(1)添加事件处理程序的不同。dom0级只能在冒泡阶段调用事件处理程序。dom2级事件模型通过addEventListener支持在冒泡和捕获阶段注册事件处理程序。而ie事件模型通过attachEvent在事件冒泡阶段注册事件处理程序。

(2)事件处理程序的event参数和this的作用域不同。addEventListener中的this就指向当前事件元素,event就是当前事件对象。而attachEvent的this指向window,event是全局对象作用域window中的event对象,但是同时也会作为参数直接传递给事件处理程序函数。但是在只支持ie事件模型的浏览器中通过dom0级方法注册的事件处理程序中的event,只能通过全局的window.event进行访问,但无论在哪个浏览器中,通过dom0级注册的事件处理程序中的this也是指向当前事件元素,可以做到很好的跨浏览器兼容。

(3) 移除事件监听。通过dom0级注册的事件处理程序,通过 element.onclick=null;这样的形式来移除注册事件。通过dom2级事件注册的时间处理程序通过removeEventListener来移除事件处理程序,而ie事件模型通过datachEvent来移除。

(4)阻止默认事件模型和阻止事件冒泡的方法。dom2级可以通过preventDefault来阻止事件的默认行为。ie通过returnValue属性为false来阻止事件的默认行为。dom2采用stopPropagation方法来阻止冒泡,而ie通过cancelBubble属性为true来阻止冒泡。

4 鼠标事件

A表示B元素的外部,B表示元素,C表示B的子元素

鼠标事件有以下几种:

mouseover:从A到B时触发,冒泡

mouseenter:从A到B时触发,并且不冒泡,DOM3级出现的事件

mouseleave:从B到A时触发,并且不冒泡,DOM3级出现的事件

mouseout:从B到A,或者从C到B时触发,冒泡

mousemove:B到B时触发

mousedown:按下任意鼠标按钮时触发

mouseup:释放鼠标按钮时触发

click:在同一个元素相继触发mousedown和mouseup才会触发click事件,任意一个被取消,都不会触发click

dbclick:连续两次click才能触发dbclick。



更多技术分享请关注 http://hist.ac.cn/

时间: 2024-12-25 17:48:11

整理之DOM事件阶段、冒泡与捕获、事件委托、ie事件和dom模型事件、鼠标事件的相关文章

事件的冒泡和捕获

DOM事件发生后,会在当前节点和父节点之间传播(propagation). 事件传播按照传播顺序分为三个阶段.对应Event.prototype.eventPhase的三个状态: const phases = { 1: 'capture', //捕获 2: 'target', // 目标 3: 'bubble' // 冒泡 } 一. 事件传播阶段 1. 捕获阶段 事件按照window->document(window.document)->html(window.documentElement

dom捕捉事件和冒泡事件-原理与demo测试

先插入一条广告,博主经营一家发饰淘宝店,都是纯手工制作哦,开业冲钻,只为信誉!需要的亲们可以光顾一下!谢谢大家的支持!店名: 小鱼尼莫手工饰品店经营: 发饰.头花.发夹.耳环等(手工制作)网店: http://shop117066935.taobao.com/ 马上开始正题... 先参考一下百度百科对冒泡事件流的解释: ----------不喜欢读文字的同学,可以直接看下面demo,传递顺序简单明了! http://baike.baidu.com/link?url=kaeJHTii_1uVgxD

JS事件冒泡与捕获

1事件传播——冒泡与捕获 默认情况下,事件使用冒泡事件流,不使用捕获事件流.然而,在Firefox和Safari里,你可以显式的指定使用捕获事件流,方法是在注册事件时传入useCapture参数,将这个参数设为true. 2冒泡事件流 当事件在某一DOM元素被触发时,例如用户在客户名字节点上点击鼠标,事件将跟随着该节点继承自的各个父节点冒泡穿过整个的DOM节点层次,直到它遇到依附有该事件类型处理器的节点,此时,该事件是onclick事件.在冒泡过程中的任何时候都可以终止事件的冒泡,在遵从W3C标

09.04 javaScript Event 对象 时间的冒泡和捕获 节点 从HTML中通过id name 标签名 class 选择器 获取元素

# Event对象 ### Event种类 * mouseEvent * keyboardEvent * focusEvent ### 属性 * clientX * clientY * keyCode * target    具体触发事件的元素 appendChild() 方法向节点添加最后一个子节点. ### 方法 * stopPropagation()   阻止冒泡 * preventDefault()      阻止默认动作 ### 事件的冒泡和捕获 # 节点 ### 节点分类 * doc

React鼠标事件

说明:假设有一个用户名片,当鼠标滑到上面,显示用户详细信息,且用户详情卡片位置随鼠标位置改变而改变. UI框架:Material-ui 实现思路: 1.一个用户简介组件A(用于展示用户列表): 2.一个用户详情组件B(用于展示用户详情): 3.在A组件里写鼠标事件,当鼠标滑到A上,显示B组件,鼠标滑出A,隐藏B组建 鼠标事件:onMouseOver  onMouseOut 给A组件一个默认state属性,通过鼠标事件改变state值,并将state值传递给B组件 组件A import React

wxpyhon 鼠标事件例子

#encoding:utf-8 import wx import wx.aui class MyFrame(wx.Frame): def __init__(self, *args, **kwargs): wx.Frame.__init__(self, *args, **kwargs) self.mgr = wx.aui.AuiManager(self) leftpanel = wx.Panel(self, -1, size=(200, 150)) rightpanel = wx.Panel(se

浅谈Qt事件的路由机制:鼠标事件

请注意,本文是探讨文章而不是教程,是根据实验和分析得出的结果,可能是错的,因此欢迎别人来探讨和纠正. 这几天对于Qt的事件较为好奇,平时并不怎么常用,一般都是用信号,对于事件的处理,一般都是需要响应键盘按键事件的时候,也用得毫无问题,因此也没怎么注意过,翻了下一般qt的教材<精通Qt4编程(第二版)>,里面12.1是这么说的. 当用户按下一个鼠标键时,这个事件首先被发给当前拥有焦点的窗口部件. 看到这里,我第一反应是,真的是这样吗,我表示十分地好奇,于是就赶忙试验了一下.代码比较简单,没有注释

DOM事件阶段以及事件捕获与事件冒泡先后执行顺序

平时浏览这么多技术文章,如过不去实践.深入弄透它,这个技术点很快就会在脑海里模糊.要加深印象,就得好好过一遍.重要的事情说三遍,重要的知识写一遍. 开发过程中我们都希望使用别人成熟的框架,因为站在巨人的肩膀上会使得我们开发的效率大幅度提升.不过,我们也应该.必须了解其基本原理.比如DOM事件,jquery框架帮我们为我们封装和抽象了各浏览器的差异行为,为事件处理带来了极大的便利.不过浏览器逐步走向统一和标准化,我们可以更加安全地使用官方规范的接口.因为只有获得众多开发者的芳心,浏览器才会走得更远

【转载】W3C下的冒泡和捕获机制。到底是冒泡呢。还是捕获呢。一个DOM元素绑定多个事件时如何执行。

原文  http://blog.csdn.net/u011719449/article/details/23787627 在准备阿里前端面试的时候看到这么一道题. 一个DOM元素绑定两个事件,一个冒泡,一个捕获,则事件会执行多少次,执行顺序如何. 这导致了我对冒泡和捕获又进一步深入的了解.(永远都在发现自己知识匮乏的日子中度过人生真是好抓急啊.) 首先冒泡和捕获是怎么一回事. 简单点说.冒泡就是从下往上,像鱼吐泡,泡泡是从下往上升的,也就是DOM元素被触法事件时(此时的dom元素为目标元素),目