本篇主要介绍HTML DOM中的事件流和事件委托。

其他事件文章

1. HTML 事件(一) 事件的介绍

2. HTML 事件(二) 事件的注册与注销

3. HTML 事件(三) 事件流与事件委托

4. HTML 事件(四) 模拟事件操作

目录

1. 事件流

  1.1 何为事件流

  1.2 事件流的三个阶段

  1.3 addEventListener()注册事件流的阶段

  1.4 阻止事件流的传播

2. 事件委托

  2.1 何为事件委托

  2.2 ul、li场景示例

  2.3 JQuery的事件委托

    2.3.1 delegate()

    2.3.2 on()

1. 事件流 (Event Flow)

1.1 何为事件流

简单来说HTML的元素会出现嵌套的关系,比如:一个Div嵌套了一个Button按钮,当2个元素都注册了click点击事件。点击里面的Button按钮时,Div的click事件也会触发。

那么问题来了,既然都会触发,得有个触发的顺序吧?是按照Div → Button这样的顺序触发,还是按照Button → Div的顺序触发?

在之前,两大浏览器厂商网景和微软都有各自的触发顺序:

网景的浏览器采用捕获方式:按照Div → Button这样的顺序触发.

而微软的浏览器采用冒泡方式:按照Button → Div的顺序触发。

在2级DOM事件规范制定时干脆合二为一:事件流同时包含了这2个阶段。

1.2 事件流的三个阶段

1.2.1 三个阶段

2级DOM事件规范制定了事件流的三个阶段:捕获阶段目标阶段冒泡阶段

捕获阶段(Capture Phase):事件从最外层的window对象到目标节点的父节点依次触发的阶段。(从外到内)

目标阶段(Target Phase):事件在目标节点上触发时的阶段。

冒泡阶段(Bubbing Phase):事件从目标节点的父节点到最外层的window对象依次触发的阶段。(从内到外)

1.2.2 示例图

1.3 addEventListener()注册事件流的阶段

元素对象通过addEventListener()注册事件时,此方法的的第三个参数可设置本次注册是捕获阶段还是冒泡阶段。

1.3.1 addEventListener()方法说明

语法:EventTarget.addEventListener(eventName, eventHandler [, useCapture] )

参数

①eventName {string} :所要注册的事件名称,不区分大小写。此名称不需要像注册事件属性那样在前缀加上"on"。如注册鼠标点击事件,写为click。

②eventHandler {function | function Object} :函数或者函数对象。事件触发时所需要执行的函数;当使用函数对象多次注册同一事件时,只当注册一遍。

③useCapture {boolean} 可选 :是否处于捕获阶段,默认为false。

  |-true:当前注册的事件为捕获阶段。

  |-false:当前注册的事件不为捕获阶段,为冒泡阶段。

1.3.2 示例

示例使用到Event事件对象的部分属性:

 readonly Object currentTarget :只读,获取正在处理此事件的对象。

 readonly int eventPhase :只读,表示事件的处理阶段:0表示没有正在处理,1表示捕获阶段,2表示目标阶段,3表示冒泡阶段。

 readonly Object target :只读,获取触发此事件的对象。

function clickHandle(e){
console.log("事件阶段:"+e.eventPhase+';target:'+e.target+';currentTarget:'+e.currentTarget)
} window.addEventListener('click',clickHandle,false);
window.addEventListener('click',clickHandle,true);
document.addEventListener('click',clickHandle,false);
document.addEventListener('click',clickHandle,true);
document.documentElement.addEventListener('click',clickHandle,false);
document.documentElement.addEventListener('click',clickHandle,true);
document.body.addEventListener('click',clickHandle,false);
document.body.addEventListener('click',clickHandle,true);
document.getElementById('div').addEventListener('click',clickHandle,false);
document.getElementById('div').addEventListener('click',clickHandle,true);
document.getElementById('btn').addEventListener('click',clickHandle,false);
document.getElementById('btn').addEventListener('click',clickHandle,true);

1.4 阻止事件流的传播

Event 事件对象的stopPropagation()、stopImmediatePropagation()方法可阻止事件流的后续传播。

stopImmediatePropagation()方法除了阻止事件流传播还会阻止当前事件在此元素的后续事件处理程序。

事件流的三个阶段调用这2个方法,会有不同的阻止传播方式:

1.4.1 在捕获阶段调用

说明:在捕获阶段调用stopPropagation()方法时,此元素后续的事件流都会阻止,包括捕获阶段、目标阶段、冒泡阶段

示例:在1.3.2示例代码中的body元素捕获阶段调用此方法

document.body.addEventListener('click',function(e){
console.log("事件阶段:"+e.eventPhase+';target:'+e.target+';currentTarget:'+e.currentTarget)
e.stopPropagation();
},true);

结果:事件流在body的捕获阶段就截至了,后续的阶段都没有执行

1.4.2 在目标阶段调用

说明:在目标段调用stopPropagation()方法时,捕获阶段和目标阶段会执行完毕,冒泡阶段不会被执行

示例:在1.3.2示例代码中的button按钮元素目标阶段调用此方法

document.getElementById('btn').addEventListener('click',function(e){
console.log("捕获阶段注册:事件阶段:"+e.eventPhase+';target:'+e.target+';currentTarget:'+e.currentTarget)
e.stopPropagation();
},false);
document.getElementById('btn').addEventListener('click',function(e){
console.log("冒泡阶段注册:事件阶段:"+e.eventPhase+';target:'+e.target+';currentTarget:'+e.currentTarget)
e.stopPropagation();
},true);

结果:捕获阶段和目标阶段执行完毕,冒泡阶段未被执行。

1.4.3 在冒泡阶段调用

说明:在冒泡段调用stopPropagation()方法时,捕获阶段和目标阶段会执行完毕,元素后续的冒泡阶段不会被执行

示例:在1.3.2示例代码中的body冒泡阶段调用此方法

document.body.addEventListener('click',function(e){
console.log("事件阶段:"+e.eventPhase+';target:'+e.target+';currentTarget:'+e.currentTarget)
e.stopPropagation();
},false);

结果:捕获阶段和目标阶段执行完毕,body后续的冒泡阶段未被执行

2. 事件委托(Event Delegate)

2.1 何为事件委托

HTML元素含有嵌套关系,并且事件流含有冒泡阶段。子元素的触发事件会冒泡到父元素的相同事件上。

一般情况只需给子元素注册特定的事件处理程序即可,但当子元素过多或频繁的进行增减操作怎么办?

比如一个ul包含了几十个li元素,对每个li元素进行单独的事件注册会影响性能。而现只要在父元素注册事件监听器,等待li事件触发后的冒泡阶段即可。

简单来说事件委托就是父元素监听子元素的冒泡事件

2.2 ul、li场景示例

Div容器包含了多个li子元素,在Div容器注册事件委托。

HTML代码

<div id="div">
<ul id="ul" >
<li data-key="北京">北京</li>
<li data-key="上海">上海</li>
<li data-key="杭州">杭州</li>
</ul>
</div>

JS代码

document.getElementById('div').addEventListener('click',function(e){
var value=e.target.attributes['data-key'].value; // 获取目标阶段元素的'data-key'属性的值
console.log(value);
});

  

2.3 JQuery的事件委托

在JQuery中,父元素可调用delegate()、on()作为事件委托使用。

2.3.1 delegate()

语法:$('父元素').delegate( selector [, eventType] [, eventData], handler )

参数

①selector {string} :子元素的选择器、

②eventType {eventType} 可选 :触发的事件类型。如:click。

③eventData {object} 可选 :触发事件时event.data指向的值。

④handler {function} :事件注册的处理程序。

示例

$('#div').delegate('li', 'click', function() {
var v = $(this).data('key');
console.log(v);
});

2.3.2 on()

说明:JQuery1.7版本开始时,推荐on()代替delegate()方法。

语法:$('元素').on( events [, selector ] [, data ], handler )

参数

①events {string} :一个或多个事件名称。

②selector {string} 可选 :子元素选择器。若无此值,表示元素注册本身的事件。若含有此值,表示只有子元素的事件触发,才会触发注册的事件。

③data {object} 可选 :触发事件时的event.data指向的值。

④handler {function} :事件注册的处理程序。

示例

$('#div').on('click','li',function(e) {
var v = $(this).data('key');
console.log(v);
});

  

End
菜单加载中...

HTML 事件(三) 事件流与事件委托的更多相关文章

  1. WPF路由事件三:自定义路由事件

    与依赖项属性类似,WPF也为路由事件提供了WPF事件系统这一组成.为一个类型添加一个路由事件的方式与为类型添加依赖项属性的方法类似,添加一个自定义路由事件的步骤: 一.声明路由事件变量并注册:定义只读 ...

  2. python全栈开发day49-jquery的位置信息、事件流、事件对象,事件委托,事件绑定和解绑

    一.昨日内容回顾    1. jQuery的属性操作 1) html属性操作:attr 2) DOM属性操作:prop 3) 类样式操作:addClass.removeClass.toggleClas ...

  3. JS事件流、事件监听、事件对象、事件委托

    JS事件流: 01.DOM级别和DOM事件 02.JS事件流:页面中接收事件的顺序 事件冒泡阶段-->处于目标阶段-->事件捕获阶段 (事件捕获总发生在事件冒泡前面) 03.捕获:从外向里 ...

  4. [已转移]js事件流之事件冒泡的应用----事件委托

    该文章已转移到博客:https://cynthia0329.github.io/ 什么是事件委托? 它还有一个名字叫事件代理. JavaScript高级程序设计上讲: 事件委托就是利用事件冒泡,只指定 ...

  5. js:事件(注册、解绑、DOM事件流、事件对象、事件委托)

    1.注册事件 (1)传统方式注册事件 <body> <button id="b1">请点击</button> <script> va ...

  6. js--事件流、事件委托、事件阶段

    前言 JavaScript 与 HTML 的交互是通过事件实现的,事件代表文档或浏览器窗口中某个有意义的时刻.可以使用仅在事件发生时执行的监听器(也叫处理程序)订阅事件.本文总结一下 JS 中的事件相 ...

  7. JavaScript事件详解-jQuery的事件实现(三)

    正文 本文所涉及到的jQuery版本是3.1.1,可以在压缩包中找到event模块.该篇算是阅读笔记,jQuery代码太长.... Dean Edward的addEvent.js 相对于zepto的e ...

  8. JS 事件冒泡整理 浏览器的事件流

    JavaScript与HTML的交互通过事件来实现.而浏览器的事件流是一个非常重要的概念.不去讨论那些古老的浏览器有事件捕获与事件冒泡的争议, 只需要知道在DOM2中规定的事件流包括了三个部分,事件捕 ...

  9. jQuery基础(4)- 位置信息、事件流、事件对象、事件代理、jquery事件

    一.jQuery的位置信息 jQuery的位置信是JS的client系列.offset系列.scroll系列封装好的一些简便api. 1.宽度和高度 a.获取宽度和高度,例如: .width() // ...

随机推荐

  1. JavaScript自定义浏览器滚动条兼容IE、 火狐和chrome

    今天为大家分享一下我自己制作的浏览器滚动条,我们知道用css来自定义滚动条也是挺好的方式,css虽然能够改变chrome浏览器的滚动条样式可以自定义,css也能够改变IE浏览器滚动条的颜色.但是css ...

  2. 菜鸟学Struts2——Results

    在对Struts2的Action学习之后,对Struts2的Result进行学习.主要对Struts2文档Guides中的Results分支进行学习,如下图: 1.Result Types(Resul ...

  3. PHP-解析验证码类--学习笔记

    1.开始 在 网上看到使用PHP写的ValidateCode生成验证码码类,感觉不错,特拿来分析学习一下. 2.类图 3.验证码类部分代码 3.1  定义变量 //随机因子 private $char ...

  4. Oracle碎碎念~2

    1. 如何查看表的列名及类型 SQL> select column_name,data_type,data_length from all_tab_columns where owner='SC ...

  5. ZKWeb网页框架1.2正式发布

    发行日志 https://github.com/zkweb-framework/ZKWeb/blob/master/ReleaseNotes/ReleaseNote.1.2.md 主要改动 更新 ZK ...

  6. .NET CoreCLR开发人员指南(上)

    1.为什么每一个CLR开发人员都需要读这篇文章 和所有的其他的大型代码库相比,CLR代码库有很多而且比较成熟的代码调试工具去检测BUG.对于程序员来说,理解这些规则和习惯写法非常的重要. 这篇文章让所 ...

  7. 设计模式C#合集--工厂方法模式

    简单工厂,代码: public interface ISpeak { public void Say(); } public class Hello : ISpeak { public void Sa ...

  8. Lind.DDD.Aspects通过Plugins实现方法的动态拦截~Lind里的AOP

    回到目录 .Net MVC之所以发展的如些之好,一个很重要原因就是它公开了一组AOP的过滤器,即使用这些过滤器可以方便的拦截controller里的action,并注入我们自己的代码逻辑,向全局的异常 ...

  9. 基于select的python聊天室程序

    python网络编程具体参考<python select网络编程详细介绍>. 在python中,select函数是一个对底层操作系统的直接访问的接口.它用来监控sockets.files和 ...

  10. ubuntu安装ANSYS17.2全过程

    本次介绍在Ubuntu kylin1604下安装Ansys 17.2的全部过程. 1 安装文件准备 关于ANSYS的软件安装文件,在网络上可以找到.这里采用SSQ版本的安装文件,如图所示,包含一个名为 ...