首先,讲一下为什么会有事件流模型。举个简单的例子来说,当你看着纸上一组同心圆的时候,你拿着笔点着同心圆里最小的那个圆的时候,是不是也可以说你也在点着这组同心圆的所有圆?显然是可以说的。
所以,当你点击页面上的一个button,你是不是也在点击着包含这个button的父级元素?同样,是的。这便是为什么会有事件流以及事件流模型。
事件流有两种:一种是微软公司提出的冒泡事件流,一种是网景公司提出捕获事件流。它们定义的事件传播方向恰恰相反。
例如:
<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按钮添加点击事件处理程序
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按钮添加点击事件处理程序
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级