一、事件的捕获与冒泡

由W3C规定的DOM2标准中,一次事件的完整过程包括三步:捕获→执行目标元素的监听函数→冒泡,在捕获和冒泡阶段,会依次检查途径的每个节点,如果该节点注册了相应的监听函数,则执行监听函数。以下面的HTML结构为例:

<div id="parentdiv">父亲<div id="childdiv">孩子</div>
</div>

  执行的流程应该是这样的:

  下面是一组例子,分别点击孩子节点可以清楚的看到第三个参数的影响:

父亲

孩子

父亲节点的监听函数在捕获阶段执行:
var parent1 = document.getElementById('parentdiv1');
var child1 = document.getElementById('childdiv1');
parent.addEventListener('click',function(){alert('父亲被点击了');},true);//第三个参数为true
child.addEventListener('click',function(){alert('孩子被点击了');},false);
父亲

孩子

父亲节点的监听函数在冒泡阶段执行:
var parent2 = document.getElementById('parentdiv2');
var child2 = document.getElementById('childdiv2');
parent.addEventListener('click',function(){alert('父亲被点击了');},false);//第三个参数为false
child.addEventListener('click',function(){alert('孩子被点击了');},false);
父亲

孩子

父亲节点的监听函数在捕获冒泡阶段都执行:
var parent3 = document.getElementById('parentdiv3');
var child3 = document.getElementById('childdiv3');
parent.addEventListener('click',function(){alert('父亲被点击了');},true);//第三个参数为true
parent.addEventListener('click',function(){alert('父亲被点击了');},false);//第三个参数为false
child.addEventListener('click',function(){alert('孩子被点击了');},false);

  如果不想让事件向上冒泡,可以在监听函数中调用event.stopPrapagation()来完成,这样父亲节点就捕捉不到该事件了。在实际的开发中,这一用处还是挺多的。

二、事件委托机制

知道了事件的捕获冒泡机制,我们可以利用它来实现更方便的程序控制,事件委托便是最典型的应用之一。下面来说说javascript中的事件委托机制。什么叫委托呢?想想我们现实生活中,自己不想干的事,让别人来帮忙完成,这就是把事情“委托”给别人。Javascript的事件委托机制也是这个道理,本来一个监听函数要处理节点a触发的事件,现在把这个监听函数绑定到节点a的父层节点上,让它的父辈来完成事件的监听,这样就把事情“委托”了过去。在父辈元素的监听函数中,可通过event.target属性拿到触发事件的原始元素,然后再对其进行相关处理。

那这样做有什么好处呢?最大的用处便是监听动态增加的元素。比如我们现在有这样的需求,点击下面每个列表项弹出各自的内容,现在随着web应用的盛行,网页中使用异步请求来动态加载节点已经变的很普遍,所以我们点击下方的按钮要在列表中增加一项,并且点击新增加的节点也要弹出内容。HTML结构如下:

<ol id="olist"><li>列表内容1</li><li>列表内容2</li><li>列表内容3</li><li>列表内容4</li><li>列表内容5</li>
</ol>

  若我们使用之前的监听器绑定方式,需要遍历所有的li元素并监听,代码应该是这样的:

var listArray = document.getElementById('olist').childNodes;
for(var i=0;i<listArray.length;i++){listArray[i].addEventListener('click',function({alert(this.innerText);});
}

  运行效果如下:

  1. 列表内容1
  2. 列表内容2
  3. 列表内容3
  4. 列表内容4
  5. 列表内容5

  可以发现当新增元素后,点击它并没有弹出内容。那是当然的了,因为我们并没有给新增的元素绑定监听器,为了实现点击新增元素也弹出内容,我们不得不在每次新增一个元素后,再进行一次绑定。加一个绑一个,加一个绑一个,累不累啊!你不累浏览器都累了!这样做导致的性能开销是可想而知的,而且浏览器还要维系n多元素与应的监听函数的映射关系,会占用大量内存。

面对这样拖沓冗杂的代码,你是不是已经不能忍,想要高喊一声:大地!快使用光能力量!好,接下来该秘密武器登场了,看看使用事件委托的效果,代码如下:

var olist = document.getElementById('olist');
olist.addEventListener('click',function(){alert(event.target.innerText);
},false);

  看看实际运行的效果:

  1. 列表内容1
  2. 列表内容2
  3. 列表内容3
  4. 列表内容4
  5. 列表内容5

  我们并未给li元素绑定任何监听器,而是监听它的父元素ul,等到事件冒泡上来的时候,在处理函数中通过event.target获得触发事件的li元素,进行相关处理。这样做的好处是显而易见的,首先只进行了一次监听器的绑定,浏览器轻松,其次动态增加元素后你也不必要再绑定监听器,你也轻松。正所谓大家好才是真的好!

本篇的基本内容就介绍完了,你是不是感觉有点奇妙,我平时写程序的时候没关心这些也仍然能完成工作呀?那我就得问你是不是使用js框架,使用jQuery了,事实上,jQuery提供的on、live等方法就已经对事件委托进行了封装,为委托机制的推广悄悄做了底层贡献,你没感觉到而已。jQuery中的各种事件监听方式也需要我们有一个清楚的了解,才能正确的使用,高效的完成工作。这些内容将放在下一篇介绍。

Javascript事件模型系列(二)事件的捕获-冒泡机制及事件委托机制相关推荐

  1. Javascript事件模型系列(一)事件及事件的三种模型

    一.开篇 在学习javascript之初,就在网上看过不少介绍javascript事件的文章,毕竟是js基础中的基础,文章零零散散有不少,但遗憾的是没有看到比较全面的系列文章.犹记得去年这个时候,参加 ...

  2. 八大数据分析模型之——事件模型(二)

    诸葛君说:在日常的数据分析中,常用的有8大模型:用户模型(点我回顾).事件模型.漏斗分析模型.热图分析模型.自定义留存分析模型.粘性分析模型.全行为路径分析模型.用户分群模型,其中,"事件模 ...

  3. Javascript模块化编程系列二: 模块化的标准化(CommonJS AMD)

    前言 Javascript模块化编程系列一: 模块化的驱动 在前一篇介绍了为什么要进行Javascript模块化编程.至于如何实现模块化,不同的开发组织和个人具体的实现方式肯定是不一样.如何统一一个规 ...

  4. 事件分发(二)ViewGroup和View对触摸事件的分发流程

    接着上篇<Activity对触摸事件的分发流程>,这篇我们讲<ViewGroup和View对触摸事件的分发流程>. 1.ViewGroup对触摸事件的分发流程 ViewGrou ...

  5. JavaScript中的事件传播(DOM2标准事件模型)

    在所有的现代浏览器当中--除了IE9之前的版本--都实现了DOM2标准事件模型,这个事件模型规定:每一个DOM元素所触发的事件都要经历三个阶段:一.捕获阶段:二.目标对象本身的事件处理程序调用阶段:三 ...

  6. JavaScript 事件模型 事件处理机制

    这篇文章对于了解Javascript的事件处理机制非常好,将它全文转载于此,以备不时之需. 什么是事件? 事件(Event)是JavaScript应用跳动的心脏 ,也是把所有东西粘在一起的胶水.当我们 ...

  7. 标准事件模型和IE事件模型

    前言:在上一篇博客中总结了0级DOM事件模型和2级DOM事件模型,打铁趁热就在谈谈标准事件模型和IE事件模型的区别吧. 一. 标准事件模型 在JavaScript中把标准事件模型的执行分为三个阶段,即 ...

  8. 用例子解释事件模型和事件代理

    事件模型 事件传播模型 在说事件代理之前,先来说一下事件模型. 在浏览器开发的早期,面对事件触发模型的问题,所有的程序员都认为事件触发不应该是直接触发的,而应该在文档中有一个传播的过程,然而事件传播的 ...

  9. Java事件模型与Android事件模型的比较

    主要内容: Android App开发时,上层用的是Java语言,二者都有事件处理机制,例如,JavaGUI中的按钮点击事件,Android Button的点击事件等. 本节通过Java代码的使用,和 ...

最新文章

  1. nginx配置文件说明
  2. [云炬创业学笔记]第一章创业是什么测试6
  3. 数据段描述符和代码段描述符(二)——《x86汇编语言:从实模式到保护模式》读书笔记11
  4. .net 技术类网址
  5. java 可重入锁 clh_Java并发编程系列-(4) 显式锁与AQS
  6. Android 保持屏幕常亮
  7. plsql oracle client没有正确安装(plsql连接远程数据库)
  8. 97. ExtJS之EditorGridPanel afteredit属性
  9. 舒尔特方格训练注意力游戏
  10. 3dmax2014 uv用法_3DSMAX演示一个硬表面模型UV展开的方法
  11. 甄别客户需求,提高解决问题的效率
  12. 在所有数据库的所有数据中搜索关键字
  13. 24小时极限挑战WPF:LOLVoiceExtractor(WPF/C++DLL)实战--(图片修复,增加程序包)
  14. git拉取项目、提交代码简单教程
  15. 输入90输公因数java_关于Java中的几个数论中的知识
  16. 谭浩强 《C程序设计》(第五版)第二章
  17. 如何利用Python和win32编程避免重复性体力劳动(三)——文本框操作:WM_GETTEXT 和WM_SETTEXT
  18. Scipy.sparse模块中的coo_matrix、csc_matrix、csr_matrix函数
  19. TG Pro for Mac(硬度温度检测工具)
  20. Cocos2d-x入门(计算机游戏开发课程笔记)

热门文章

  1. 黑客与网管的30天较量
  2. 【EventBus】事件通信框架 ( 订阅方法注册 | 注册 事件类型 - 订阅类 + 订阅方法 到指定集合 | 取消注册 数据准备 )
  3. 【Android 插件化】插件化简介 ( 组件化与插件化 )
  4. 【鸿蒙 HarmonyOS】界面跳转 ( AbilitySlice 之间的界面跳转 | AbilitySlice 之间的值传递 )
  5. 【嵌入式开发】ARM 异常向量表 ( 异常概念 | 异常处理流程 | 异常向量 | 汇编代码 )
  6. 【网站建设】Linux上安装MySQL - 12条命令搞定MySql
  7. linux下部署svn服务器
  8. AtCoder Grand Contest 013D: Piling Up 题解
  9. PIE_SDK.NET功能表
  10. 【《Objective-C基础教程 》笔记】(八)OC的基本事实和OC杂七杂八的疑问