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

  本篇主要介绍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);
});

  

==================================系列文章==========================================

本篇文章:5.5 HTML 事件(三) 事件流与事件委托

Web开发之路系列文章

时间: 2024-08-24 04:40:51

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

事件流和事件委托

导读: 当我们点击一个元素触发该元素上绑定的点击事件时,同时也点击了该元素的父元素以及祖先元素等元素,如果该元素的父元素以及祖先元素等元素也绑定了点击事件,那么它们的执行顺序是怎样的呢?为了解决这个问题,所以有了事件流的概念. 1.事件流 当一个HTML元素产生一个事件时,该事件会在元素节点与根结点之间的路径传播,路径所经过的结点都会收到该事件,这个传播过程可称为DOM事件流.简单地说:事件流就是描述页面中接收事件的顺序.其包含三个阶段: 捕获阶段:事件从 Document 节点自上而下向目标节

委托和事件(三)

C#中的委托和事件 引言 如果你看过了 C#中的委托和事件 一文,我想你对委托和事件已经有了一个基本的认识.但那些远不是委托和事件的全部内容,还有很多的地方没有涉及.本文将讨论委托和事件一些更为细节的问题,包括一些大家常问到的问题,以及事件访问器.异常处理.超时处理和异步方法调用等内容. 为什么要使用事件而不是委托变量? 在 C#中的委托和事件 中,我提出了两个为什么在类型中使用事件向外部提供方法注册,而不是直接使用委托变量的原因.主要是从封装性和易用性上去考虑,但是还漏掉了一点,事件应该由事件

js事件流之事件冒泡的应用----事件委托

什么是事件委托? 它还有一个名字叫事件代理. JavaScript高级程序设计上讲: 事件委托就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件. 用取快递来解释这个现象,大家认真领会一下事件委托到底是一个什么原理: 有三个同事预计会在周一收到快递.为签收快递,有两种办法:一是三个人在公司门口等快递:二是委托给前台MM代为签收.现实当中,我们大都采用委托的方案(公司也不会容忍那么多员工站在门口就为了等快递).前台MM收到快递后,她会判断收件人是谁,然后按照收件人的要求签收,甚

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

JavaScript与HTML的交互通过事件来实现.而浏览器的事件流是一个非常重要的概念.不去讨论那些古老的浏览器有事件捕获与事件冒泡的争议, 只需要知道在DOM2中规定的事件流包括了三个部分,事件捕获阶段.处于目标阶段.事件冒泡阶段. 1.事件捕获 事件捕获,是从document元素开始,越高级的父级元素越早接收到事件,因此这是一个从上而下的过程. A): 坑一:新插入的子元素没有绑定点击事件 一个ul元素中初始的状态有4个li元素,我们可以循环给li元素添加click事件,执行我们想要的动作

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

一.jQuery的位置信息 jQuery的位置信是JS的client系列.offset系列.scroll系列封装好的一些简便api. 1.宽度和高度 a.获取宽度和高度,例如: .width() // 获取匹配元素集合中的第一个元素的宽度值,内容宽度,不含padding .height() // 获取匹配元素集合中的第一个元素的高度值,内容高度,不含padding 注意:这个方法不接受任何参数..css(‘width’)(或.css(‘height’))和 .width()(或.height()

DOM事件探秘之事件流与事件处理程序

1.事件流:描述的是从页面中接受事件的顺序 ①.事件冒泡流:即时间最开始由最具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播至最不具体的那个节点(文档).      栗子:若<body><div><input type="button"/></div></body>次结构,点击按钮时,默认点了按钮的容器 默认点了body,默认点了html,默认点了document. ②.事件捕获:不太具体的节点应该更早接收到事

js事件流、事件处理程序/事件侦听器

1.事件流 事件冒泡 IE的事件流叫做事件冒泡(event bubbling),即事件开始时由最具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播到较为不具体的节点(文档). 事件捕获 事件捕获的思想是不太具体的节点应该更早的接收到事件,而最具体的节点应该在最后接收到节点.事件捕获的用意在于事件到达预定目标之前捕获它. DOM事件流 “DOM2级事件流”规定的事件流包括三个阶段:事件捕获阶段.处于目标阶段和冒泡阶段.首先发生的是事件捕获,为截获事件提供了机会.然后是实际的目标接收到

js学习笔记:事件——事件流、事件处理程序、事件对象

Javascript与HTML之间的交互是通过事件实现的. 事件,就是文档或浏览器窗口中发生的一些特定的交互瞬间. 可以使用侦听器来预定事件,以便事件发生时执行相应代码. 事件流 事件流描述的是从页面中接受事件的顺序. 事件冒泡 IE的事件流叫做事件冒泡,即事件开始是由最具体的元素接收,然后逐级向上传播到较为不具体的节点(文档). 如果点击了页面中的一个div元素,那么这个click事件可能会按照如下顺序传播: < div> < body> < html> docume

深入理解DOM事件机制系列第一篇——事件流

× 目录 [1]历史 [2]事件冒泡 [3]事件捕获[4]事件流 前面的话 javascript操作CSS称为脚本化CSS,而javascript与HTML的交互是通过事件实现的.事件就是文档或浏览器窗口中发生的一些特定的交互瞬间,而事件流(又叫事件传播)描述的是从页面中接收事件的顺序.本文将详细介绍该部分的内容 历史 当浏览器发展到第四代时(IE4及Netscape4),浏览器开发团队遇到了一个很有意思的问题:页面的哪一部分会拥有某个特定的事件?想象画在一张纸上的一组同心圆.如果把手指放在圆心