JS事件的捕获和冒泡阶段

JS事件的捕获和冒泡阶段

这里介绍两个事件模型:IE事件模型与DOM事件模型

  1. IE内核浏览器的事件模型是冒泡型事件(没有捕获事件过程),事件句柄的触发顺序是从ChildNode到ParentNode。
 <div id="ancestor"> <button id="child"> child</button> <button id="child2"> child2</button> 
</div> 
  1. 以上的HTML代码在IE内核下,事件是这样传播的:

    1、Button#child;
    2、div#ancestor;
    3、Body;
    4、Document

    DOM标准的浏览器事件是:捕获事件和冒泡事件。

    捕获事件过程

    1、Window
    2、Document
    3、Body
    4、Div#ancestor
    5、Button#child

    冒泡事件过程

    6、Div#ancestor
    7、Body
    8、Document
    9、Window

当开发者在一个元素上注册了事件后,这个事件的响应顺序是从window(最顶层)开始一级一级的向下传播,然后到了该元素后事件捕获过程结束,事件开如冒泡,一级一级向父层元素冒泡(请注意第6步)。

当然,开发者可以很轻松的决定DOM标准的浏览器中的事件需要在哪个传播过程触发。

事件的注册机制

DOM标准的浏览器事件注册方法是通过addEventListener方法注册,而IE内核的浏览器则是通过attachEvent方法注册。

addEventListener

addEventListener方法带有三个参数,分别是:eventType、handler、useCapture。

a. eventType不带有on字符串;
b. handler参数是一个事件句柄,这个函数或方法带有一个事件对象参数;
c. useCapture参数决定了事件句柄触发在哪种事件传播阶段,如果useCapture为true则为捕获阶段,反之则为冒泡阶段。

// html文件<div id="ancestor"> <button id="child"> child</button> <button id="child2"> child2</button> 
</div> 
// js代码
let ancestorHandler = function (e){ console.log("div");
}
let childHandler = function (e){ console.log("button");
};document.querySelector('#ancestor').addEventListener('click',ancestorHandler,false);//注意第三个参数 ,注册了一个在冒泡阶段触发的事件句柄document.querySelector('#child').addEventListener('click',childHandler,true);//注意第三个参数 ,注册了一个在捕获阶段的事件句柄

输出结果:

"button"
"div"

当用户在这个DIV元素上点击时,事件的执行顺序是childHandler、ancestorHandler。

原因:按钮的事件是在捕获阶段触发的,也就是从上到下,而DIV的事件是注册在冒泡阶段,也就是点击了这个按钮开始从这个按钮的位置往上冒泡。

其中useCapture我们设置了true,我们选择在捕获阶段处理该handler。
其中useCapture我们设置了false,我们选择在冒泡阶段处理该handler。

我们来看一下事件的流程:

  1. 当用户点击DIV上的元素时,触发监听事件
  2. 执行childHandler
  3. 执行ancestorHandler

原因:按钮的事件是在捕获阶段触发的,也就是从上到下的顺序,而DIV的事件是注册在冒泡阶段,也就是在点击了这个按钮button之后,从这个位置往上冒泡。

阻止事件的冒泡:

DOM事件对象提供了stopPropagation方法用于阻止事件流。

var ancestorHandler = function (e){ //...... 
}, 
childHandler = function (e){ e.stopPropagation(); //...... 
}; 

以上代码在childHandler函数中添加了e.stopPropagation()代码片段,它将阻止事件流,事件流包括捕获阶段及冒泡阶段的事件流。

再修改上面的代码如下:

let ancestorHandler = function (e){ console.log("div");
}
let childHandler = function (e){ console.log("button");
};
document.querySelector('#ancestor').addEventListener('click',ancestorHandler,true);//注意第三个参数 
document.querySelector('#child').addEventListener('click',childHandler,true);//注意第三个参数 

输出结果:

// 点击child
"div"
"button"
// 点击child2
"div"

分析一下上面的代码
点击child按钮

1.当用户点击div内的child按钮元素时,将会依次触发ancestorHandler、childHandler函数
2.原因是我们将div#ancestor的事件注册到捕获阶段了,也就是从上到下。
3.用户点击div区域,仅仅先触发了ancestorHandler函数,因为事件流被阻止了
4.处理完ancestorHandler事件之后,再捕获到child点击事件,然后执行childHandler函数

点击child2按钮

1.当用户点击child按钮时,会触发点击div内的元素触发后的handler,也就是ancestorHandler函数
2.然后输出div

removeEventListener

删除监听事件处理函数的方法,主要是针对移除 addEventListener() 方法添加的监听事件。

removeEventListener同样带有三个参数,分别是:eventType、handler、useCapture,和addEventListener是同样的。

// 向 <div> 元素添加事件句柄
document.getElementById("myDIV").addEventListener("mousemove", myFunction, false);// 移除 <div> 元素的事件句柄
document.getElementById("myDIV").removeEventListener("mousemove", myFunction, false);

示例:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>vincent</title>
<style>
#myDIV 
{background-color: coral;border: 1px solid;padding: 50px;color: white;
}
</style>
</head>
<body><div id="myDIV"> div 元素添加了  onmousemove 事件句柄,在你移动鼠标时会显示随机数。<p>点击按钮移除 DIV 的事件句柄。</p><button onclick="removeHandler()" id="myBtn">点我</button>
</div>
<p id="demo"></p>
<script>
document.getElementById("myDIV").addEventListener("mousemove", myFunction);
function myFunction() 
{document.getElementById("demo").innerHTML = Math.random();
}
function removeHandler() 
{document.getElementById("myDIV").removeEventListener("mousemove", myFunction);
}
</script></body>
</html>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/536129.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2016: C语言实验——打印金字塔

2016: C语言实验——打印金字塔 Description 输入n值&#xff0c;打印下列形状的金字塔&#xff0c;其中n代表金字塔的层数。 Input 输入只有一个正整数n。 Output 打印金字塔图形&#xff0c;其中每个数字之间有一个空格。 Sample Input 3 Sample Output 11 2 1 1 2 …

Anuglar中正确导入RxJS库

Anuglar中正确导入RxJS库 目前Angular2中的已经内建支持RxJS,所以我们在使用的时候可以直接导入使用了。 理解操作符导⼊ 在使用创建依赖于 RxJS 组件,服务,指令等等时, 你可能遇到处理运算符导⼊的问 题。 在项⽬中引⼊操作符最主要的⽅式像下⾯这样导⼊: import rxj…

1495: 蛇行矩阵

1495: 蛇行矩阵 Description 蛇形矩阵是由1开始的自然数依次排列成的一个矩阵上三角形。 Input 本题有多组数据&#xff0c;每组数据由一个正整数N组成。&#xff08;N不大于100&#xff09; Output 对于每一组数据&#xff0c;输出一个N行的蛇形矩阵。两组输出之间不要额…

递归基础之N皇后问题

递归基础之N皇后问题 Description 在nn 格的棋盘上放置彼此不受攻击的n 个皇后。按照国际象棋的规则&#xff0c;皇后可以攻击与之 处在同一行或同一列或同一斜线上的棋子。n后问题等价于在nn格的棋盘上放置n个皇后&#xff0c; 任何2 个皇后不放在同一行或同一列或同一斜线上…

X86和X86_64和AMD64的由来

为什么叫X86和X86_64和AMD64 为什么大家叫x86为32位系统呢 相信大家在大学里面有很多人都玩过8086&#xff08;微处理器&#xff09;&#xff0c;这是一个可编程的系统&#xff0c;他是由intel开发的&#xff0c;英特尔出了划时代的8086之后&#xff0c;后来使用该架构出了80…

回炉-熄灯问题

进来突然意识到算法的重要性&#xff0c;可惜已经没有充足的时间去进行专业的训练了&#xff0c;只能慢慢挤时间做几个题练习一下聊以安慰&#xff0c;希望能多坚持几天吧&#xff0c;奉劝各位想学算法的同学一定要趁早啊。 poj1222 解析见郭炜老师的程序设计与算法&#xff…

ngrx初识

ngrx初识 在使用之前需要安装ngrx npm install @ngrx/store --save 或者 yarn add @ngrx/store ngrx/store:保存了ReduxAPI的核心概念,使用RxJS扩展的Redux实现。使用可观察对象来简化了监听事件的订阅等操作。 dispatch&reducer&state dispatcher,reducer,state…

回炉-特殊密码锁

题目&#xff1a;特殊密码锁 001:特殊密码锁 描述 有一种特殊的二进制密码锁&#xff0c;由n个相连的按钮组成&#xff08;n<30&#xff09;&#xff0c;按钮有凹/凸两种状态&#xff0c;用手按按钮会改变其状态。 然而让人头疼的是&#xff0c;当你按一个按钮时&#x…

Angular的NgModule

Angular的NgModule NgModule作为Angular模块的核心,也是组织者,官方有很长的文档来介绍他,包括每一个API。 @NgModule文件的定义方式 import { BrowserModule } from @angular/platform-browser; import { NgModule } from @angular/core;import { AppComponent } from ./ap…

回炉-拨钟问题

题目&#xff1a;拨钟问题 1166:拨钟问题 描述 有9个时钟&#xff0c;排成一个3*3的矩阵。 |-------| |-------| |-------| | | | | | | | |---O | |---O | | O | | | | | | | |-------| |-------| …

Ubuntu扩展触摸屏触控错位修复

Ubuntu扩展触摸屏触控错位修复 当我们ubuntu外接一个触摸显示器的时候&#xff0c;会发现触摸扩展屏幕&#xff0c;发现操控的是主屏幕&#xff0c;我写了一个脚本去修复。 #! /bin/bash #------------------------------------------------------------------------------ #…

目标检测与分割总结

目标检测最常用的三个模型&#xff1a;Faster R-CNN、SSD和YOLO Faster R-CNN架构 在Faster RCNN中&#xff0c;候选框是经过RPN产生的&#xff0c;然后再把各个“候选框”映射到特征图上&#xff0c;得到RoIs。 Faster R-CNN步骤&#xff1a; (1) 由输入图片产生的区域候选…

shell脚本单词去重多个文件

shell脚本单词去重多个文件 例如要求如下&#xff1a; 有多个txt文件&#xff0c;每个文件内有多行单词 中间为英文的”,”&#xff0c;或者中文的”&#xff0c;”逗号作为分隔符。 world,世界 set&#xff0c;设置 good,好&#xff0c;商品 .... 将这些文件汇总去除重复…

win10连接烟台大学校园网

第一步 右键网络图标&#xff0c;打开网络管理中心 第二步&#xff1a; 设置添加新的网络&#xff0c;方法步骤如下&#xff1a; 第三步&#xff1a;新建VPN连接&#xff0c;注意协议为L2TP 第四步&#xff1a; 第五步&#xff1a; 第六步&#xff1a; 创建结束后进入更…

Angular国际化方案

Angular国际化方案 首先和大家推荐一个xlf文件的操作工具,支持合并和编辑功能,github,到release界面下载。 对于Angular国际化,官方提供了i18n方案,也就是标签的方式,通过angular CLI来识别。国际化方案必须在编译前定义下来,所以不能动态翻译。也就是当有人切换语言时,…

模拟退火算法(TSP问题)

模拟退火算法解决TSP问题 算法思想 模拟退火算法&#xff08;Simulate Anneal&#xff0c;SA&#xff09;是一种通用概率演算法&#xff0c;用来在一个大的搜寻空间内找寻命题的最优解 模拟退火算法来源于固体退火原理&#xff0c;将固体加温至充分高&#xff0c;再让其徐徐…

2-docker 安装

2-docker 安装 Ubuntu 安装 由于 apt 源使用 HTTPS 以确保软件下载过程中不被篡改。因此&#xff0c;我们首先需要添加使用 HTTPS 传输的软件包以及 CA 证书。 $ sudo apt-get update$ sudo apt-get install \apt-transport-https \ca-certificates \curl \gnupg-agent \sof…

U-Net++粗略解释

Paper&#xff1a;UNet: A Nested U-Net Architecture for Medical Image Segmentation u-net网络的基本拓扑结构 目前最先进的图像分割模型是各种个同样的 encoder-decoder架构&#xff0c;他们具有一个关键的相似性&#xff1a;skip connections&#xff0c;它可以将编码器…

Spring中的组合模式

组合模式是一种对象设计模式&#xff0c;它允许你将对象组合成树形结构以表示“部分-整体”的层次结构&#xff0c;使得客户端以统一的方式处理单个对象和对象的组合。在Spring框架中&#xff0c;组合模式被广泛应用&#xff0c;让我们深入分析一下。 在Spring中&#xff0c;组…

Docker+Nginx部署Angular

DockerNginx部署Angular 在部署Angular生产环境之前&#xff0c;需要电脑已经安装docker。 添加Dockerfile 在已经完成的Angular项目的项目根目录下添加Dockerfile文件。 Dockerfile文件内容&#xff1a; FROM nginx:1.11-1.11-alpine COPY index.html /usr/share/nginx/ht…