以下测试在非IE浏览器中进行(如Chrome和火狐,因为IE不支持事件捕获)
1.先分析下面代码:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="zh-CN">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gbk" />
<title>浏览器事件机制——阻止事件传播</title>
<style>
div#divGrandpa3 {padding:40px;background-color:#f00;}
div#divFather3 {padding:40px;background-color:#0f0;}
div#divSon3 {padding:40px;background-color:#00f;}
</style>
</head>
<body>
<div id="divGrandpa3" style="width:300px;height:200px;" onclick = "showGrandpa0();" > I am Grandpa
<div id="divFather3" style="width:200px;height:120px;" > I am father
<div id="divSon3" style="width:100px;height:40px;" >
点击我 I am son
</div>
</div>
</div>
<script>
function showSon(e) {alert("I am son");}
function showSon0(e) {alert("Dom0: I am son");}
function showFather(e) {
alert("I am father");
}
function showFather0(e) {alert("Dom0: I am father");}
function showGrandpa(e) {
e.stopPropagation();//在捕获阶段,阻止事件 传播
alert("I am Grandpa");
}
function showGrandpa0(e) {alert("Dom0: I am Grandpa");}
//3.捕获阶段 和 冒泡阶段 都 执行事件处理函数, 只在非IE浏览器中有效
var grandpa3 = document.getElementById("divGrandpa3");
var father3 = document.getElementById("divFather3");
var son3 = document.getElementById("divSon3");
if(window.addEventListener)
{
grandpa3.addEventListener("click", showGrandpa, true);
father3.addEventListener("click", showFather, true);
son3.addEventListener("click", showSon, true);
}
else if (window.attachEvent)
{
grandpa2.attachEvent("onclick", showGrandpa);
father2.attachEvent("onclick", showFather);
son2.attachEvent("onclick", showSon);
}
</script>
</body>
</html>
上面代码中三句,分别注册了三个DOM2级别的事件处理函数,
grandpa3.addEventListener("click", showGrandpa, true);
father3.addEventListener("click", showFather, true);
son3.addEventListener("click", showSon, true);
其中,在showGrandpa中调用了
e.stopPropagation();//在捕获阶段,阻止事件 传播,
另外,<div id="divGrandpa3" style="width:300px;height:200px;" onclick = "showGrandpa0();" >
div标签中定义onclick = "showGrandpa0();"属性,定义一个DOM1级别的事件处理函数
这样,根据事件传播顺序:
a.事件捕捉阶段,事件对象沿着document一直传播到发生事件的那个对象(即文档的目标节点,比如id为son的div),这个过程叫事件捕获.
b.事件到达目标节点,如果目标节点指定了事件处理函数,则执行这个函数
当点击 son时,显示 I am Grandpa(事件捕获过程中),然后事件传播终止,调用结束.
当点击grandpa时,先显示 Dom0: I am Grandpa 然后再显示 I am Grandpa
这里不是应该先进行 捕获吗, 应该先执行 grandpa3.addEventListener("click", showGrandpa, true); 注册的函数吗?
2. 分析下面代码:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" lang="zh-CN"> <head> <meta http-equiv="Content-Type" content="text/html; charset=gbk" /> <title>浏览器事件机制——阻止事件传播</title> <style> div#divGrandpa3 {padding:40px;background-color:#f00;} div#divFather3 {padding:40px;background-color:#0f0;} div#divSon3 {padding:40px;background-color:#00f;} </style> </head> <body> <div id="divGrandpa3" style="width:300px;height:200px;" > I am Grandpa <div id="divFather3" style="width:200px;height:120px;" > I am father <div id="divSon3" style="width:100px;height:40px;" > 点击我 I am son </div> </div> </div> <script> function showSon(e) {alert("I am son");} function showSon0(e) {alert("Dom0: I am son");} function showFather(e) { alert("I am father"); } function showFather0(e) {alert("Dom0: I am father");} function showGrandpa(e) { e.stopPropagation();//在捕获阶段,阻止事件 传播 alert("I am Grandpa"); } function showGrandpa0(e) {alert("Dom0: I am Grandpa");} //3.捕获阶段 和 冒泡阶段 都 执行事件处理函数, 只在非IE浏览器中有效 var grandpa3 = document.getElementById("divGrandpa3"); var father3 = document.getElementById("divFather3"); var son3 = document.getElementById("divSon3"); if(window.addEventListener) { grandpa3.addEventListener("click", showGrandpa, true); father3.addEventListener("click", showFather, true); son3.addEventListener("click", showSon, true); grandpa3.οnclick=showGrandpa0; } else if (window.attachEvent) { grandpa2.attachEvent("onclick", showGrandpa); father2.attachEvent("onclick", showFather); son2.attachEvent("onclick", showSon); } </script> </body> </html>
上面代码中四句:
grandpa3.addEventListener("click", showGrandpa, true);
father3.addEventListener("click", showFather, true);
son3.addEventListener("click", showSon, true);
grandpa3.οnclick=showGrandpa0;
前三句添加了DOM2级别的时间处理程序,
第四句grandpa3.οnclick=showGrandpa0;
这个相当于覆盖了上面的onclick = "showGrandpa0();"
即同时在html标签中定义onclick = "showGrandpa0();" 和 在代码中定义 grandpa3.οnclick=showGrandpa0;
相当于只在代码中 定义 grandpa3.οnclick=showGrandpa0;
但是不仅仅是简单的覆盖,这里执行的顺变得不一样了:
当点击 son时,显示 I am Grandpa(事件捕获过程中),然后事件传播终止,调用结束.
当点击grandpa时,先显示 I am Grandpa 然后再显示 Dom0: I am Grandpa
这又是什么情况?
3. 结论
1.虽然在 showGrandpa()函数中调用了e.stopPropagation();阻止事件传播,
但是使用onclick = "showGrandpa0();"方式注册的事件处理函数,会在事件捕获之前执行?
2. 在代码中使用grandpa3.οnclick=showGrandpa0;方式注册的
事件处理函数会在事件到达目标节点时执行(上面情况2中,在点击grandpa时,可看成是在事件传播阻止之前,
事件已经到达目标节点,所以执行了showGrandpa0())?
推测: 在事件传播过程中,当事件到达目标节点后,
使用html标签中类似于οnclick="showGrandpa0();"方式注册的事件处理函数先执行,
然后再执行 使用grandpa3.addEventListener("click", showGrandpa, true);方式注册的DOM2事件处理函数
如果在代码中使用,grandpa3.οnclick=showGrandpa0;方式注册事件处理函数,
则会覆盖html标签中类似与οnclick="showGrandpa0();"方式注册的事件处理函数,
并且 grandpa3.οnclick=showGrandpa0;方式注册事件处理函数
会在 grandpa3.addEventListener("click", showGrandpa, true);方式注册的DOM2事件处理函数
执行过了之后再执行.