全面解析javascript事件流模型以及各事件流模型在浏览器中的兼容性情况

来源:互联网 发布:windows 运行ios 编辑:程序博客网 时间:2024/06/05 04:30

首先,讲一下为什么会有事件流模型。举个简单的例子来说,当你看着纸上一组同心圆的时候,你拿着笔点着同心圆里最小的那个圆的时候,是不是也可以说你也在点着这组同心圆的所有圆?显然是可以说的。

所以,当你点击页面上的一个button,你是不是也在点击着包含这个button的父级元素?同样,是的。这便是为什么会有事件流以及事件流模型。

事件流

事件流有两种:一种是微软公司提出的冒泡事件流,一种是网景公司提出捕获事件流。它们定义的事件传播方向恰恰相反。

  • 事件冒泡(Event Capturing): 是一种从下往上的传播方式。事件最开始由最具体的元素(也就是DOM最底层的子节点), 然后逐渐向上传播到最不具体的那个节点(也就是DOM中最高层的父节点)。
  • 事件捕获(Event Bubbling): 是一种从上到下的传播方式。事件最开始由不太具体的节点最早接受事件, 而最具体的节点最后接受事件。

例如:

<!DOCTYPE html><html><head lang="en">    <meta charset="UTF-8">    <title></title></head><body><div id="myDiv">Click me!</div></body></html>

在冒泡型事件流中click事件传播顺序为div -> body -> html -> document

这里写图片描述

在捕获型事件流中click事件传播顺序为document -> html -> body -> div

这里写图片描述

之前,微软公司的IE系列浏览器主张冒泡型事件处理,网景公司的Netscape系列浏览器主张捕获型,谁也说服不了谁,之后W3C组织制定了DOM标准事件流,但可惜的是网景公司并未撑到DOM标准制定就被收购了,但它的捕获事件流的思想却被借鉴了下来。

DOM事件流:

DOM标准采用捕获+冒泡。两种事件流都会触发DOM的所有对象,从document对象开始,也在document对象结束。

这里写图片描述

DOM标准规定事件流包括三个阶段:事件捕获阶段、处于目标阶段和事件冒泡阶段。

  • 事件捕获阶段:实际目标(div)在捕获阶段不会接收事件。也就是在捕获阶段,事件从document到html再到body就停止了。上图中为1~3.

  • 处于目标阶段:事件在div上发生并处理。但是事件处理会被看成是冒泡阶段的一部分。

  • 冒泡阶段:事件又传播回document

事件流模型

现在常用事件流模型的可以说就是2种:DOM0 模型,DOM2模型。(有些说是3种,HTML事件处理程序、DOM0 模型、DOM2模型,虽然说HTML事件处理程序不存在浏览器的兼容性问题,但个人不推荐使用,可自行了解)

DOM 0 模型:

如要给btn按钮添加点击事件处理程序

<input type="button" id="btn">

在js代码区添加事件处理程序和绑定关系

var btn = document.getElementById("btn");btn.onclick = function showMessage(){    alert("hello world");}

如果要移除该点击事件处理程序

btn.onclick = null;

DOM 0模型并不是W3C组织制定的标准,但是由于在W3C组织制定标准之前,这种方式广被各种浏览器所采用,到现在各种浏览器也都支持,所以就被保留了下来。

说明:DOM 0模型不存在浏览器兼容性的问题,也就是说,它被各种浏览器支持,可跨浏览器使用。

注意:通过DOM 0方法添加的事件,无法控制是冒泡事件流还是捕获事件流,但是现今流行的浏览器中(safari、IE、opera、chrome、Firefox)都把其在冒泡事件流阶段处理。

DOM 2 模型:

如要给btn按钮添加点击事件处理程序

<input type="button" id="btn">

js区添加事件处理程序和绑定关系

     var btn= document.getElementById("btn");     btn.addEventListener("click", function () {       alert("innerCircle的click事件在捕获阶段被触发");    },true);     btn.addEventListener("click", function () {       alert("innerCircle的click事件在冒泡阶段被触发");    },false);

事件绑定监听函数的方式 : addEventListener(eventType, handler, useCapture).

当useCapture取值false为冒泡阶段调用事件处理程序;当useCapture取值true为捕获阶段调用事件处理程序。

移除事件的方式:removeEventListener(eventType, handler, useCapture)

说明:DOM 2 模型并未被IE9以下版本支持即 IE(6,7,8)不支持DOM 2 注册和移除事件的方式,且只支持冒泡事件流,不支持DOM事件流。

在IE(6,7,8)版本中,注册事件和移除事件的写法是:

var btn3 = document.getElementById("btn3");btn3.attachEvent("onclick", showMessage);//注册事件btn3.detachEvent("onclick", showMessage);//移除事件function showMessage(){    alert("hello world");}

但是IE 9及以上版本(IE 10 ,IE11,IE edge)支持DOM 事件流且支持DOM2注册和移除事件的方式。

所以,我们可以按照对DOM2的支持把浏览器分为两类:IE(6,7,8)和 其它浏览器。

因此jquery等这些js库就封装了跨浏览器的事件处理方式。

总结

如果同时出现DOM0和DOM2事件处理程序,那么不同浏览器处理它们的优先级会怎样呢?

chrome/opera/safari等webkit内核的浏览器:DOM2级 DOM0级
firefox浏览器和IE浏览器(指IE9及以上版本)会将DOM0级事件优先调用:DOM0级 DOM2级

原创粉丝点击