javascript 事件冒泡机制

来源:互联网 发布:淘宝儿童女外衣 编辑:程序博客网 时间:2024/05/21 21:42

javascript 事件冒泡机制

概念

在一个对象上触发某类事件(比如单击onclick事件),如果此对象定义了此事件的处理程序,那么此事件就会调用这个处理程序,
如果没有定义此事件处理程序或者事件返回true,那么这个事件会向这个对象的父级对象传播,从里到外,
直至它被处理(父级对象所有同类事件都将被激活),或者它到达了对象层次的最顶层,即document对象(有些浏览器是window)。

作用

事件冒泡允许多个操作被集中处理(把事件处理器添加到一个父级元素上,避免把事件处理器添加到多个子级元素上),它还可以让你在对象层的不同级别捕获事件。

事件模型

  • 冒泡型事件:事件按照从最特定的事件目标到最不特定的事件目标(document对象)的顺序触发。
    IE 5.5: div -> body -> document    IE 6.0: div -> body -> html -> document    Mozilla 1.0: div -> body -> html -> document -> window
  • 捕获型事件(event capturing):事件从最不精确的对象(document 对象)开始触发,然后到最精确(也可以在窗口级别捕获事件,
    不过必须由开发人员特别指定)。

  • DOM事件流:同时支持两种事件模型:捕获型事件和冒泡型事件,但是,捕获型事件先发生。两种事件流会触及DOM中的所有对象,
    从document对象开始,也在document对象结束。

DOM事件模型最独特的性质是,文本节点也触发事件(在IE中不会)。

支持W3C标准的浏览器在添加事件时用addEventListener(event,fn,useCapture)方法,基中第3个参数useCapture是一个Boolean值,
用来设置事件是在事件捕获时执行,还是事件冒泡时执行。而不兼容W3C的浏览器(IE)用attachEvent()方法,此方法没有相关设置,
不过IE的事件模型默认是在事件冒泡时执行的,也就是在useCapture等于false的时候执行,所以把在处理事件时把useCapture设置为false是比较安全,
也实现兼容浏览器的效果。

这里写图片描述

过程

事件捕获阶段:事件从最上一级标签开始往下查找,直到捕获到事件目标(target)。
事件冒泡阶段:事件从事件目标(target)开始,往上冒泡直到页面的最上一级标签。

示例

假设一个元素div,它有一个下级元素p。

<div>  <p>元素</p></div>

这两个元素都绑定了click事件,如果用户点击了p,它在div和p上都触发了click事件,那这两个事件处理程序哪个先执行呢?事件顺序是什么?

分析

两种模型
以前,Netscape和Microsoft是不同的实现方式。
Netscape中,div先触发,这就叫做事件捕获。
Microsoft中,p先触发,这就叫做事件冒泡。
两种事件处理顺序刚好相反。IE只支持事件冒泡,Mozilla, Opera 7 和 Konqueror两种都支持,旧版本的Opera’s 和 iCab两种都不支持 。


事件捕获
当你使用事件捕获时,父级元素先触发,子级元素后触发,即div先触发,p后触发。


事件冒泡
当你使用事件冒泡时,子级元素先触发,父级元素后触发,即p先触发,div后触发。


W3C模型
W3C模型是将两者进行中和,在W3C模型中,任何事件发生时,先从顶层开始进行事件捕获,直到事件触发到达了事件源元素。然后,再从事件源往上进行事件冒泡,直到到达document。
程序员可以自己选择绑定事件时采用事件捕获还是事件冒泡,方法就是绑定事件时通过addEventListener函数,它有三个参数,第三个参数若是true,则表示采用事件捕获,若是false,则表示采用事件冒泡。
ele.addEventListener(‘click’,doSomething2,true)
true=捕获
false=冒泡


注意

  • 不是所有的事件都能冒泡。以下事件不冒泡:blur、focus、load、unload。

  • 事件捕获到达顶层的目标在不同浏览器或不同浏览器版本也是有区别的。在IE6中HTML是接收事件冒泡的,另外大部分浏览器将冒泡延续到window对象,即……body→documen→window。

  • 阻止冒泡并不能阻止对象默认行为。比如submit按钮被点击后会提交表单数据,这种行为无须我们写程序定制。

阻止事件冒泡

  • 在W3c中,使用 stopPropagation() 方法
  • 在IE下设置 cancelBubble = true
  • 在捕获的过程中 stopPropagation()

阻止事件的默认行为

  • 在W3c中,使用preventDefault()方法
  • 在IE下设置window.event.returnValue = false

事件委托模式

把本来每个子节点要处理的逻辑,都交给父节点来完成,通过事件冒泡实现,父节点通过甄别事件的 target 来确定子节点,进行不同的逻辑处理。

使用事件委托的优点:

  • 管理的函数变少了。不需要为每个元素都添加监听函数。对于同一个父节点下面类似的子元素,可以通过委托给父元素的监听函数来处理事件
  • 可以方便地动态添加和修改元素,不需要因为元素的改动而修改事件绑定。
  • JavaScript和DOM节点之间的关联变少了,这样也就减少了因循环引用而带来的内存泄漏发生的概率。

这里写图片描述

javascript 中代理方式

通过创建代理对象来操作目标对象,从编程模式上实现了对某些对象的隐藏,可以保护这些对象不被随便访问和修改。

var delegate = function (client, clientMethod) {    return function () {        return clientMethod.apply(client, arguments);    }}var ClassA = function () {    var _color = "red";    return {        getColor : function () {            console.log("Color: " + _color);        },        setColor : function (color) {            _color = color;        }    };};var a = new ClassA();a.getColor();a.setColor("green");a.getColor();console.log("执行代理!");var d = delegate(a, a.setColor);d("blue");console.log("执行完毕!");a.getColor();


查看原文:http://localhost:8080/?p=119