浅谈JS事件冒泡
今天要跟大家谈的是事件冒泡,这个事件呢,也是两面性的,有时候给我们带来bug,有时候优点也很明显。我们就一起来看看它的真面目。
首先看看事件冒泡是什么?
事件冒泡 :当一个元素接收到事件的时候 会把他接收到的事件传给自己的父级,一直到window 。(注意这里传递的仅仅是事件 并不传递所绑定的事件函数。所以如果父级没有绑定事件函数,就算传递了事件 也不会有什么表现 但事件确实传递了。)
只看这句话,或许不是那么好理解,下面来看个栗子:
var div1 = document.getElementById("div1");
var div2 = document.getElementById("div2");
div2.onclick = function(){alert(1);};
div1.onclick = function(){alert(2);};//父亲
//html代码
<div id="div1">
<div id="div2"></div>
</div>
代码很简单,就是两个父子关系的div,然后分别加了点击事件,当我们在div2里面点击的时候,会发现弹出了一次1,接着又弹出了2,这说明点击的时候,不仅div2的事件被触发了,它的父级的点击事件也触发了,这种现象就叫做冒泡。点击了div1,自己父级的点击事件也会被触发。
再看个栗子
var div1 = document.getElementById("div1");
var div2 = document.getElementById("div2")
div1.onclick = function(){alert(2);}; // 父亲
//html代码 <div id="div1"> <div id="div2"></div> </div>
大家可以看一下效果图,相比于第一个例子,代码已经把儿子的点击事件去掉,只留下了父级的,测试的结果是当只点击了儿子,会弹出2,由此证明了当点击了儿子,父亲的点击事件被触发,执行了自己绑定的函数。由于一些人会以为显示出来儿子在父亲里面的时候,自然点了儿子相当于点了父亲,所以这个例子我故意把两个盒子绝对定位在了两个不同的位置,所以点击事件给页面显示出来的位置是没关系的,而是跟html代码中的位置有关系。
可能有人会有疑惑下面这种情况,为啥没有弹出两次:
var div1 = document.getElementById("div1");
var div2 = document.getElementById("div2");
div2.onclick = function(){alert(1);};
div1.onclick = function(){}; //父亲
//html代码
<div id="div1">
<div id="div2"></div>
</div>
这里我们要注意,我们传递的仅仅是事件触发,也就是说当点击div2仅仅触发了父级的点击事件,并没有把自己的绑定的函数给父级,父级的执行情况,取决于自己所绑定的函数,因为在这里它绑定的函数是空,自然没什么表现。有些人在这里有误解,所以强调一下。
以上大概就是冒泡的形式了,而大多数时候,冒泡也带来了一些困扰,下面我们看一个栗子:

我们的需求是点击上面红色的面板让下面粉色的面板显示,点击其他地方再让粉丝面板隐藏。于是我们会这样写js代码:
<script>
var div2 = document.getElementById("div2");
var div1 = document.getElementById("div1"); div2.onclick = function(){ //红色面板事件
div1.style.display = "block";
};
document.onclick = function(){
div1.style.display = "none";
}
</script>
这个时候我们测试发现,怎么点击红色面板,粉丝面板都不会显示了,为什么呢?就是冒泡的原因,我们来分析下代码,当点击div2的时候,他会触发父亲级别的点击事件,然后一层一层的往上传,所以document的点击事件自然也被触发了,然后执行了自己身上的绑定事件,让粉色面板消失。所以当你点击div2的时候首先,让粉丝面板显示,只是事件执行太快了,很快又执行了document的点击事件,让面板隐藏。 有兴趣的可以再两个事件之间加一个弹出,就可以测试。
那么这个时候我们肯定不希望有冒泡了,所以解决办法就是取消冒泡了:(后来补充)
取消事件冒泡有两种方式:
标准的W3C 方式:e.stopPropagation();这里的stopPropagation是标准的事件对象的一个方法,调用即可
非标准的IE方式:ev.cancelBubble=true; 这里的cancelBubble是 IE事件对象的属性,设为true就可以了
通常我们会封装这样一个函数:
function stopBubble(e) {
//如果提供了事件对象,则这是一个非IE浏览器
if ( e && e.stopPropagation )
//因此它支持W3C的stopPropagation()方法
e.stopPropagation();
else
//否则,我们需要使用IE的方式来取消事件冒泡
window.event.cancelBubble = true;
}
这个时候需要用到事件对象里的 cancelBubble属性,把它设为true即可,ev.cancelBubble=true;所以改进后的代码如下:<script>
var div2 = document.getElementById("div2");
var div1 = document.getElementById("div1");
div2.onclick = function(ev){ // 红色面板加事件
div1.style.display = "block";
stopBubble(ev);//这样就不会再冒泡给父级了
};
document.onclick = function(){
div1.style.display = "none";
}
function stopBubble(e) {
//如果提供了事件对象,则这是一个非IE浏览器
if ( e && e.stopPropagation )
//因此它支持W3C的stopPropagation()方法
e.stopPropagation();
else
//否则,我们需要使用IE的方式来取消事件冒泡
window.event.cancelBubble = true;
}
其实冒泡还有一大优点,就是事件委托,而且经常用到,还能提高很大的性能,想要了解,看下篇博客喽,我们沐晴,下回不见不散。
浅谈JS事件冒泡的更多相关文章
- 浅谈js冒泡事件1
什么是JS事件冒泡?: 在一个对象上触发某类事件(比如单击onclick事件),如果此对象定义了此事件的处理程序,那么此事件就会调用这个处理程序,如果没有定义此事件处理程序或者事件返回true,那么这 ...
- 浅谈JS之AJAX
0x00:什么是Ajax? Ajax是Asynchronous Javascript And Xml 的缩写(异步javascript及xml),Ajax是使用javascript在浏览器后台操作HT ...
- 浅谈js拖拽
本文来自网易云社区 作者:刘凌阳 前言 本文依据半年前本人的分享<浅谈js拖拽>撰写,算是一篇迟到的文章. 基本思路 虽然现在关于拖拽的组件库到处都是,HTML5也把拖放纳入了标准.但考虑 ...
- 浅谈JS中的!=、== 、!==、===的用法和区别 JS中Null与Undefined的区别 读取XML文件 获取路径的方式 C#中Cookie,Session,Application的用法与区别? c#反射 抽象工厂
浅谈JS中的!=.== .!==.===的用法和区别 var num = 1; var str = '1'; var test = 1; test == num //tr ...
- 什么是JS事件冒泡?
什么是JS事件冒泡?: 在一个对象上触发某类事件(比如单击onclick事件),如果此对象定义了此事件的处理程序,那么此事件就会调用这个处理程序,如果没有定义此事件处理 程序或者事件返回true,那么 ...
- js事件冒泡和事件委托
js事件冒泡 js所谓的事件冒泡就是子级元素的某个事件被触发,它的上级元素的该事件也被递归执行 html: <ul class="clearfix" data-type=&q ...
- 浅谈JS中的闭包
浅谈JS中的闭包 在介绍闭包之前,我先介绍点JS的基础知识,下面的基础知识会充分的帮助你理解闭包.那么接下来先看下变量的作用域. 变量的作用域 变量共有两种,一种为全局变量,一种为局部变量.那么全局变 ...
- 什么是JS事件冒泡
什么是JS事件冒泡? 在一个对象上触发某类事件(比如单击onclick事件),如果此对象定义了此事件的处理程序,那么此事件就会调用这个处理程序,如果没有定义此事件处理程序或者事件返回true,那么这个 ...
- 阻止JS事件冒泡传递(cancelBubble 、stopPropagation)
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx. ...
随机推荐
- Effective Java 41 Use overloading judiciously
The choice of which overloading to invoke is made at compile time. // Broken! - What does this progr ...
- Java基础の乱弹琴二:break关键字
Java中的break一般用于 跳出一个switch或者循环. 跳出switch基本不用赘述. break跳出循环一般是跳出当前一层循环. 如若需要跳出多层循环可以在break后加标签,然后把标签标注 ...
- C++中对象初始化
在C++中对象要在使用前初始化,永远在使用对象之前先将它初始化. 1.对于无任何成员的内置类型,必须手工完成此事. 例如: int x=0; double d; std::cin>>d; ...
- Hadoop Shell命令字典(可收藏)
可以带着下面问题来阅读: 1.chmod与chown的区别是什麽?2.cat将路径指定文件的内容输出到哪里?3.cp能否是不同之间复制?4.hdfs如何查看文件大小?5.hdfs如何合并文件?6.如何 ...
- 谷歌和HTTPS
谷歌和HTTPS HTTPS被觉得是加强互联网安全的次要部分,而且使用广泛.google近来做了一份关于数据加密近况的陈述. 正在陈述的最新部分中,提到了google以及第三方构造对于数据加密所做的贡 ...
- ckplayer播放器去掉右边的开关灯分享插件
在上一篇文章中介绍了如何使用ckplayer播放器,但是有的人不需要CK播放器右边的开关灯分享插件,那么就需要把该插件给去掉,方法也很简单. 第一步:先打开ckplayer.js里找到下面三行删除掉 ...
- HDU 4041 Eliminate Witches! --模拟
题意: 给一个字符串,表示一颗树,要求你把它整理出来,节点从1开始编号,还要输出树边. 解法: 模拟即可.因为由括号,所以可以递归地求,用map存对应关系,np存ind->name的映射,每进入 ...
- 前端MVC学习总结(四)——NodeJS+MongoDB+AngularJS+Bootstrap书店示例
这章的目的是为了把前面所学习的内容整合一下,这个示例完成一个简单图书管理模块,因为中间需要使用到Bootstrap这里先介绍Bootstrap. 示例名称:天狗书店 功能:完成前后端分离的图书管理功能 ...
- jira与readmine区别
JIRA适合多人的团队(100+),而Readmine适合中小型团队. Redmine是用ruby开发的基于web的项目管理软件,免费.JIRA收费Redmine可以创建子任务,而jira不易创建子任 ...
- 纯CSS3制作皮卡丘动画壁纸
前言 明天就放假了,趁着今晚的空挡时间来写这篇博客——这是我昨晚实现的一个简单的CSS3动画效果.话说还得缘起我逛了一下站酷网,然后不小心看到了一张皮卡丘的手机壁纸,觉得很可爱,然后觉得这种效果是可以 ...