浅谈js的事件冒泡和事件捕获
本文地址:https://www.cnblogs.com/christineqing/p/7607113.html
前言:
这篇文章起源于上次工作上的原因,在事件上出的bug,所以就抽空写出一篇,也便于自己以后查阅,如若有幸被您阅读的话,小妹备感荣幸,文章仅为个人理解,如果内容有误的还望海涵,在您时间还方便的时候,希望能告知小妹!谢谢!
什么是事件?
事件是文档和浏览器窗口中发生的特定的交互瞬间。 事件是javascript应用跳动的心脏,也是把所有东西黏在一起的胶水,当我们与浏览器中web页面进行某些类型的交互时,事件就发生了。
事件可能是用户在某些内容上的点击,鼠标经过某个特定元素或按下键盘上的某些按键,事件还可能是web浏览器中发生的事情,比如说某个web页面加载完成,或者是用户滚动窗口或改变窗口大小。
什么是事件流:
事件流描述的是从页面中接受事件的顺序,但有意思的是,微软(IE)和网景(Netscape)开发团队居然提出了两个截然相反的事件流概念,IE的事件流是事件冒泡流(event bubbling),而Netscape的事件流是事件捕获流(event capturing)。
第一种:事件冒泡
IE提出的事件流叫做事件冒泡,即事件开始时由最具体的元素接收,然后逐级向上传播到较为不具体的节点,看一下以下示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body onclick="bodyClick()"> <div onclick="divClick()">
<button onclick="btn()">
<p onclick="p()">点击冒泡</p>
</button>
</div>
<script> function p(){
console.log('p标签被点击')
}
function btn(){
console.log("button被点击")
}
function divClick(event){
console.log('div被点击');
}
function bodyClick(){
console.log('body被点击')
} </script> </body>
</html>
接下来我们点击一下页面上的p元素,看看会发生什么:
正如上面我们所说的,它会从一个最具体的的元素接收,然后逐级向上传播, p=>button=>div=>body..........事件冒泡可以形象地比喻为把一颗石头投入水中,泡泡会一直从水底冒出水面。
第二种:事件捕获
网景公司提出的事件流叫事件捕获流。
事件捕获流的思想是不太具体的DOM节点应该更早接收到事件,而最具体的节点应该最后接收到事件,针对上面同样的例子,点击按钮,那么此时click事件会按照这样传播:(下面我们就借用addEventListener的第三个参数来模拟事件捕获流)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body> <div>
<button>
<p>点击捕获</p>
</button>
</div>
<script>
var oP=document.querySelector('p');
var oB=document.querySelector('button');
var oD=document.querySelector('div');
var oBody=document.querySelector('body'); oP.addEventListener('click',function(){
console.log('p标签被点击')
},true); oB.addEventListener('click',function(){
console.log("button被点击")
},true); oD.addEventListener('click', function(){
console.log('div被点击')
},true); oBody.addEventListener('click',function(){
console.log('body被点击')
},true); </script> </body>
</html>
同样我们看一下后台的打印结果:
正如我们看到的,和冒泡流万全相反,从最不具体的元素接收到最具体的元素接收事件 body=>div=>button=>p
DOM事件流:
‘DOM2级事件’规定的事件流包含3个阶段,事件捕获阶段、处于目标阶段、事件冒泡阶段。首先发生的事件捕获为截获事件提供机会,然后是实际的目标接收事件,最后一个阶段是事件冒泡阶段,可以在这个阶段对事件做出响应。
在DOM事件流中,事件的目标在捕获阶段不会接收到事件,这意味着在捕获阶段事件从document到<p>就停止了,下个阶段是处于目标阶段,于是事件在<p>上发生,并在事件处理中被看成冒泡阶段的一部分,然后,冒泡阶段发生,事件又传播回document。
下面是我们模拟它的示例:
看看后台给出什么结果:
就是这样一个流程,先捕获,然后处理,然后再冒泡出去。
关于DOM 2级事件处理程序:
DOM 2级事件定义了两方法:用于处理添加事件和删除事件的操作: 添加事件 addEventListener() 删除事件 removeEventListener()
所有DOM节点中都包含这两个方法,并且他们都包含3个参数: (1) 要处理的事件方式(例如:click,mouseover,dbclick.....) (2)事件处理的函数,可以为匿名函数,也可以为命名函数(但如果需要删除事件,必须是命名函数) (3)一个布尔值,代表是处于事件冒泡阶段处理还是事件捕获阶段(true:表示在捕获阶段调用事件处理程序;false:表示在冒泡阶段调用事件处理程序)
使用DOM 2级事件处理程序的主要好处是可以添加多个事件处理程序,事件处理会按照他们的顺序触发,通过addEventListener添加的事件只能用removeEventListener来移除,移除时传入的参数与添加时使用的参数必须相同,这也意味着添加的匿名函数将无法移除,(注意:我们默认的第三个参数都是默认false,是指在冒泡阶段添加,大多数情况下,都是将事件处理程序添加到事件的冒泡阶段,这样可以最大限度的兼容各个浏览器)
//这是一个DOM 2级事件 添加事件最简单的方式(此时添加的是一个匿名函数)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body> <button>按钮</button>
<script>
var btn=document.querySelector('button');
btn.addEventListener('click',function(){
console.log('我是按钮')
},false) //当第三个参数不写时,也是默认为false(冒泡时添加事件)
</script> </body>
</html>
那么我们试试命名函数:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body> <button>按钮</button>
<script>
var btn=document.querySelector('button');
btn.addEventListener('click',foo,false);
function foo(){
console.log('我是按钮')
}
//其实操作就是把写在里面的函数拿到了外面,而在原来的位置用函数名来代替
</script>
</body>
</html>
那么我们添加两个事件试试:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body> <button>按钮</button>
<script>
var btn=document.querySelector('button');
//第一个事件
btn.addEventListener('click',foo,false);
function foo(){
console.log('我是按钮')
}
//第二个事件
btn.addEventListener('click',newFoo,false);
function newFoo(){
console.log('我是新按钮')
}
</script>
</body>
</html>
那么我们看看后台有没有执行,执行顺序是怎样的:
所以说,我们添加两个事件是可以的,事件的顺序就是按照我们程序写的顺序执行的
那我们试试DOM 0级事件处理程序
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<button onclick="foo()" onclick="newFoo()">按钮</button>
<script>
function foo(){
console.log(2)
}
function newFoo(){
console.log(9)
}
</script>
</body>
</html>
看一下结果:
只执行了第一个事件,第二个被忽略,这并不是我们想要的结果,而addEventLiener是会把两个事件都去执行的。
结尾:
以上就是事件冒泡,事件捕获,dom事件流,dom2级事件流的所有内容,谢谢阅读!
浅谈js的事件冒泡和事件捕获的更多相关文章
- 【转载】浅谈事件冒泡与事件捕获 - javascript 事件代理
原文:https://segmentfault.com/a/1190000000749838 事件冒泡与事件捕获 事件冒泡和事件捕获分别由微软和网景公司提出,这两个概念都是为了解决页面中事件流(事件发 ...
- JS事件(事件冒泡和事件捕获)
事件流:描述的是在页面中接收事件的顺序 事件冒泡:由最具体的元素接收,然后逐级向上传播至最不具体的元素的节点(文档) 事件捕获:最不具体的节点先接收事件,而最具体的节点应该是最后接收事件 DOM中:用 ...
- js进阶 12-2 彻底弄懂JS的事件冒泡和事件捕获
js进阶 12-2 彻底弄懂JS的事件冒泡和事件捕获 一.总结 一句话总结:他们是描述事件触发时序问题的术语.事件捕获指的是从document到触发事件的那个节点,即自上而下的去触发事件.相反的,事件 ...
- JS事件冒泡与事件捕获怎么理解?
在js中存在事件冒泡与事件捕获两种概念,这两个概念都是为了解决页面中事件流(事件发生顺序)的问题. 事件冒泡(dubbed bubbling) 事件冒泡我们从字面意思理解就是当用户行为触发我们页面的定 ...
- JS中的事件绑定,事件捕获,事件冒泡以及事件委托,兼容IE
转载请注明出处:http://www.cnblogs.com/zhangmingze/p/4864367.html ● 事件分为三个阶段: 事件捕获 --> 事件目标 --> ...
- js 事件冒泡和事件捕获
事件流:指的是网页中元素接受事件的顺序,它是一个概念,而不是具体的实际的东西 事件冒泡:指的是内层元素的事件,会触发包含着此元素的外层元素的事件,触发的顺序是:由内而外的 例如: <!DOCTY ...
- 彻底弄懂JS的事件冒泡和事件捕获
先上结论:在事件执行流中有两种执行方式.一种是事件冒泡(即事件的执行顺序是从下往上执行的) ; 另一种是捕获(即事件的执行顺序是从上往下执行的); 阻止事件冒泡: return false; ...
- js高级:event,事件冒泡,事件捕获
1.事件 浏览器客户端上客户触发的行为都称为事件 所有的事件都是天生自带的,不需要我们去绑定,只需要我们去触发. 通过 obj.事件名=function(){} 事件名:onmouseover 鼠标悬 ...
- JS高级:事件冒泡和事件捕获;
1.事件:浏览器客户端上客户触发的行为成为时事件:所有的事件都是天生自带的,不需要我们去绑定,只需要我们去触发 当用户触发一个事件时,浏览器的所有详细信息都存在一个叫做event的对象上,我们把它叫做 ...
随机推荐
- C# JsonConvert 序列号 DateTime类型 格式多T
序列化字符串后,值变成了"2018-02-05T00:00:00" 序列化时候 需要更改一下日期转换方式: IsoDateTimeConverter timeConverter = ...
- 201871010116-祁英红《面向对象程序设计(java)》第一周学习总结
项目 内容 <面向对象程序设计(java)> https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.com/ ...
- 算法问题实战策略 PICNIC
下面是另一道搜索题目的解答过程题目是<算法问题实战策略>中的一题oj地址是韩国网站 连接比较慢 https://algospot.com/judge/problem/read/PICNIC ...
- 03. Go 语言容器
Go语言容器(container) 变量在一定程度上能满足函数及代码要求.如果编写一些复杂算法.结构和逻辑,就需要更复杂的类型来实现.这类复杂类型一般情况下具有各种形式的存储和处理数据的功能,将它们称 ...
- C++ 虚函数的说明
虚函数的几点说明: 1. 当一个成员函数定义为虚函数时,其派生类中的同名函数也自动为虚函数.无论其是否添加了 virtual 关键字. 为了能良好的阅读代码,请加上. 2. 父类的虚函数,就是为了让子 ...
- Android开发笔记:Android开发环境搭建
基于Eclipse开发 1. 安装JDK 首先进入JDK下载页面,选择需要的版本下载安装. JDK 下载地址:https://www.oracle.com/technetwork/java/javas ...
- 分治 FFT
为啥要叫分治\(fft\)啊,又用不到\(fft--\) 给定长度为\(n-1\)的数组\(g[1],g[2],--,g[n-1]\),求\(f[1],f[2],--,f[n]\),其中 \[f[i] ...
- 第04组 Alpha冲刺(4/4)
队名:斗地组 组长博客:地址 作业博客:Alpha冲刺(4/4) 各组员情况 林涛(组长) 过去两天完成了哪些任务: 1.分配展示任务 2.收集各个组员的进度 3.写博客 展示GitHub当日代码/文 ...
- mysql数据库的十种查询方式及多表查询
--mysql数据库的十种查询方式 -- (1)查询时起别名 SELECT id AS '编号',NAME AS '姓名',age AS '年龄' FROM student; -- (2)查询时添加常 ...
- django接口文档自动生成
django-rest_framework接口文档自动生成 只针对用到序列化和返序列化 一般还是用第三方yipi 一.安装依赖 pip3 install coreapi 二.设置 setting.py ...