对“捕获”和“冒泡”这两个概念,我想我们对冒泡更熟悉一些,因为在我们使用的所有浏览器中,都支持事件冒泡,即事件由子元素向祖先元素传播的,就 像气泡从水底向水面上浮一样。而在像firefox,chrome,safari这类所谓的标准浏览器中,事件传播还有个阶段,那就是捕获阶段,这个很少 有用武之地,所以被人疏忽遗忘也在所难免了,不常用不代表它不存在,本着科学严谨的态度,我们有必要去看一下它的庐山真面目。

事实上,捕获阶段是一个和冒泡阶段完全相反的过程,即事件由祖先元素向子元素传播,和一个石子儿从水面向水底下沉一样,要说明的是在 IE,opera浏览器中,是不存在这个阶段的。从各浏览器提供的注册事件监听的方法中可见一斑,例如适用于ie,opera的attachEvent, 有两个参数,attachEvent(”on”+type,fn),而适用于所谓标准浏览器的addEventListener则有三个参 数,addEventListener(type,fn,boolean),前面两个参数不用解释,第三个参数boolean,就是决定注册事件发生在捕 获阶段还是冒泡阶段,具体参考如下:

true : 捕获阶段

false : 冒泡阶段

事件分类
捕获型事件(非IE)、冒泡型事件(所有浏览器都支持)
捕获型事件是自上而下的,而冒泡型事件是自下而上的。下面我用一个图来直观表示:

冒泡型事件我们在工作中可能会比较多遇到,但捕获型事件怎样才会执行到呢,如果我们想要在非 IE 浏览器中要创建捕获型事件,只需将 addEventListener 的第三个参数设为true就好了。

DOME:

<!doctype html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gbk" />
<title>无标题文档</title>
<meta name="description" content="" />
<meta name="keywords" content="" />
</head> <body>
<style type="text/css">
*{margin:0;padding:0;}
h1{text-align:center;color:#666;margin-top:18px;}
#content{width:700px;height:250px;border:5px solid green;margin:20px auto;position:relative;}
#obj1{height:100px;background:#d5d5d5;}
#obj2{background:#777;}
#obj3{position:absolute;top:200px;left:150px;width:200px;background:#555;}
#obj4{height:100px;background:#999;margin-top:50px;}
.active{color:#f00;}
</style>
<h1>悟透事件的捕获和冒泡</h1>
<div id="content">
<div id="obj1">
<h2>元素a</h2>
<div id="obj2">
<h2>元素b</h2>
<div id="obj3">
<h2>元素c</h2>
</div>
</div>
</div> <div id="obj4">
<h2>元素d</h2>
</div>
</div> <script type="text/javascript">
var divs = document.getElementById("content").getElementsByTagName("div");
var count = 1;
for(var i=0;i<divs.length;i++){
bindEvent(divs[i],"click",function(){
var obj = document.createTextNode("->"+count++);
this.getElementsByTagName("h2")[0].insertBefore(obj,null);
this.className = "active";
});
} //取消事件冒泡
function stopBubble(e){
e = e||window.event;
if(e.stopPropagation){
e.stopPropagation();
}else{
e.cancelBubble = true;
}
} //绑定事件
function bindEvent(elem,type,fn){
if(elem.attachEvent){
var typeRef = "_" + type;
if(!elem[typeRef]){
elem[typeRef] = [];
}
for(var i in elem[typeRef]){
if(elem[typeRef][i] == fn){
return;
}
}
elem[typeRef].push(fn);
elem["on"+type] = function(){
for(var i in this[typeRef]){
this[typeRef][i].apply(this,arguments);
}
}
}else{
elem.addEventListener(type,fn,false);
}
} //移除事件绑定
function removeEvent(elem,type,fn){
if(elem.detachEvent){
if(elem["_"+type]){
for(var i in elem["_"+type]){
if(elem["_"+type][i] == fn){
elem["_"+type].splice(i,1);
break;
}
}
}
}else{
elem.removeEventListener(type,fn,false);
}
}
</script>
</body>
</html>

取消事件冒泡:

在默认情况下,发生在一个子元素上的单击事件(或者其他事件),如果在其父级元素绑定了一个同样的事件,此时点击子元素,click事件会首先被子元素捕获,执行绑定的事件程序,之后会被父级元素捕获,再次激发一段脚本的执行,这就是所谓的“事件冒泡”。

在通常情况下,我们只希望事件发生在它的目标而并非它的父级元素上,只需加个stopBubble方法,即可取消事件冒泡,详见以下代码:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>无标题文档</title>
<style type="text/css">
*{ margin:0; padding:0;}
</style>
</head>
<body>
<div id="obj1" style=" width:500px; height:500px; background:#000;">
<div id="obj2" style="width:400px; height:400px; background:red;"></div>
</div>
<script type="text/javascript">
//阻止事件冒泡的通用函数
function stopBubble(e){
// 如果传入了事件对象,那么就是非ie浏览器
if(e&&e.stopPropagation){
//因此它支持W3C的stopPropagation()方法
e.stopPropagation();
}else{
//否则我们使用ie的方法来取消事件冒泡
window.event.cancelBubble = true;
}
} var obj1 = document.getElementById('obj1');
var obj2 = document.getElementById('obj2');
obj1.onclick = function(){
alert('我点击了obj1');
}
obj2.onclick = function(e){
alert('我点击了obj2');
stopBubble(e);
}
</script>
</body>
</html>

现在你可能想知道,什么时候需要阻止事件冒泡?事实上,现在绝大多数情况下都可以不必在意它。但是当你开始开发动态应用程序(尤其是需要处理键盘和鼠标)的时候,就有这个必要了。

javascript事件捕获与冒泡的更多相关文章

  1. JavaScript 事件(捕获和冒泡 兼容性写法)

    事件    浏览器客户端上客户触发的行为都称为事件 所有的事件都是天生自带的 不需要人为绑定 只需要我们去触发通过obj.事件名=function(){} 我们给元素的事件绑定了一个方法 事件名:on ...

  2. JavaScript事件捕获冒泡与捕获

    事件流 JavaScript中,事件流指的是DOM事件流. 概念 事件的传播过程即DOM事件流.事件对象在 DOM 中的传播过程,被称为"事件流".举个例子:开电脑这个事,首先你是 ...

  3. 【转】JavaScript 事件顺序:冒泡和捕获

    补充说明:这篇文章通俗易懂地讲解了冒泡和捕获原理,原文来自 ppk 大侠的 quirksmode 站点.感谢网友 hh54188 的翻译. 事件的发生顺序 这个问题的起源非常简单,假设你在一个元素中又 ...

  4. javascript -- 事件捕获,事件冒泡

    使用js的时候,当给子元素和父元素定义了相同的事件,比如都定义了onclick事件,单击子元素时,父元素的onclick事件也会被触发.js里称这种事件连续发生的机制为事件冒泡或者事件捕获. 为什么会 ...

  5. dom事件不求甚解,色解事件捕获和冒泡

    以前对事件只会用jq的bind绑定一下,脑海里留着书中的事件循环,一直认为事件就是这儿循环的,最近看园子里的文章,对事件的了解更模糊了 所以我做了个小实验,总结一下看的这些零零碎碎的文章,如果总结错了 ...

  6. js中addEventListener第三个参数涉及到的事件捕获与冒泡

    js中,我们可以给一个dom对象添加监听事件,函数就是 addEventListener("click",function(){},true); 很容易理解,第一个参数是事件类型, ...

  7. Spirit带你彻底了解事件捕获和冒泡机制

    Dom标准事件模型 在Dom标准事件模型中,事件是先进行捕获,达到目标阶段时,在进行冒泡的 捕获阶段==>目标阶段==>冒泡阶段 目标元素和非目标元素 在介绍事件捕获和事件冒泡前 我们先要 ...

  8. js事件捕获和冒泡解析

    <div id="box"> <div id="box2"> <p id="test">test< ...

  9. javascript事件捕获机制,dom tree

    $(document,"a").on("click",function(){alert(2);return false;}); $("<a> ...

随机推荐

  1. Gulp:基于流的自动化构建工具

    前言 先说说为什么会使用gulp. 当你沉醉于撸代码之时,是否想过正规的前端代码需要走哪些流程,复杂的不说了,有几点想必你也思考过,比如: 1.代码的压缩合并.图片压缩怎么搞: 2.代码校验,是否规范 ...

  2. iOS高仿城觅-感谢大神分享

    项目展示,由于没有数据,所以所有的cell显示的都是我自己写的数据 抽屉 首页部分效果 首页效果 部分效果 发现 消息 搜索 设置 模糊效果 代码注释展示 代码注释展示 还有很多细节就不一一展示了,大 ...

  3. The Contiki build system 编译系统

    The Contiki build system======================== The Contiki build system is designed to make it eas ...

  4. 安装ArchLinux的参考分区方案

    其实就是从Archwiki上搬运过来的 = =. 分区方案 虽然有一些关于分区方案的通用建议,但没有严格的准则.有许多影响分区方案的因素,例如对灵活性的期望,访问速度,安全性以及可用磁盘空间的硬性限制 ...

  5. mysql 增量导入到elasticsearch

    <pre name="code" class="html">zjtest7-redis:/odbc_es# cat /odbc_es/run_mys ...

  6. C# 通过线程更新UI

    摘自:http://msdn.microsoft.com/zh-cn/library/ms171728(en-us,VS.80).aspx 关键代码(form中增加): delegate void S ...

  7. ThreadPoolExecutor参数解析

    ThreadPoolExecutor是一个非常重要的类,用来构建带有线程池的任务执行器,通过配置不同的参数来构造具有不同规格线程池的任务执行器. 写在前面的是: 线程池和任务执行器,线程池的定义比较直 ...

  8. 【czy系列赛】czy的后宫4 && bzoj1925 [Sdoi2010]地精部落

    [问题描述] czy有很多妹子,妹子虽然数量很多,但是质量不容乐观,她们的美丽值全部为负数(喜闻乐见). czy每天都要带N个妹子到机房,她们都有一个独一无二的美丽值,美丽值为-1到-N之间的整数.他 ...

  9. 【POJ1005】I Think I Need a Houseboat

    说是计算几何,其实是一道水题.直接算半圆面积即可. #include <iostream> #include <cstdlib> #include <cstdio> ...

  10. Oracle 方法

    1.递归 select zxdept from (select d.id, d.zxdept, d.RANK, d.fatherId from web_dept d start with d.id = ...