Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
事件流
事件流出現的歷史背景
當瀏覽器發展到第四代時(IE4 及 Netscape Communicator 4),瀏覽器開發團隊遇到了一個很有意思 的問題:頁面的哪一部分會擁有某個特定的事件?要明白這個問題問的是什么,可以想象畫在一張紙上 的一組同心圓。如果你把手指放在圓心上,那么你的手指指向的不是一個圓,而是紙上的所有圓。兩家 公司的瀏覽器開發團隊在看待瀏覽器事件方面還是一致的。如果你單擊了某個按鈕,他們都認為單擊事 件不僅僅發生在按鈕上。換句話說,在單擊按鈕的同時,你也單擊了按鈕的容器元素,甚至也單擊了整 個頁面。
事件流描述的是從頁面中接收事件的順序。
但有意思的是,IE 和 Netscape 開發團隊居然提出了差 不多是完全相反的事件流的概念。IE 的事件流是事件冒泡流,而 Netscape Communicator 的事件流是事件捕獲流。
IE的事件流叫做時間冒泡,即事件開始時由文檔中最內層的元素接收,然后逐級往上傳播。
<!DOCTYPE html> <html> <head> <title>Event Bubbling Example</title> </head> <body> <div id="myDiv">Click Me</div> </body> </html>
如果你單擊了頁面中的<div>元素,那么這個 click 事件會按照如下順序傳播:
div->body->html->document
也就是說,click 事件首先在<div>元素上發生,而這個元素就是我們單擊的元素。然后,click 事件沿 DOM 樹向上傳播,在每一級節點上都會發生,直至傳播到 document 對象。圖 13-1 展示了事件 冒泡的過程。
IE事件流
所有現代瀏覽器都支持事件冒泡,但在具體實現上還是有一些差別。IE5.5 及更早版本中的事件冒 泡會跳過<html>元素(從<body>直接跳到 document)。IE9、Firefox、Chrome 和 Safari 則將事件一直 冒泡到 window 對象。
Netscape Communicator 團隊提出的另一種事件流叫做事件捕獲(event capturing)。事件捕獲的思想是不太具體的節點應該更早接收到事件,而最具體的節點應該最后接收到事件。事件捕獲的用意在于在 事件到達預定目標之前捕獲它。如果仍以前面的 HTML 頁面作為演示事件捕獲的例子,那么單擊<div> 元素就會以下列順序觸發 click 事件。
document->html->body->div
在事件捕獲過程中,document 對象首先接收到 click 事件,然后事件沿 DOM 樹依次向下,一直傳播到事件的實際目標,即<div>元素 。
事件捕獲
雖然事件捕獲是 Netscape Communicator 唯一支持的事件流模型,但 IE9、Safari、Chrome、Opera 和 Firefox 目前也都支持這種事件流模型。盡管“DOM2 級事件”規范要求事件應該從 document 對象開始傳播,但這些瀏覽器都是從 window 對象開始捕獲事件的。
由于老版本的瀏覽器不支持,因此很少有人使用事件捕獲。
“DOM2級事件”規定的事件流包括三個階段:事件捕獲階段、處于目標階段和事件冒泡階段。首 先發生的是事件捕獲,為截獲事件提供了機會。然后是實際的目標接收到事件。最后一個階段是冒泡階段,可以在這個階段對事件做出響應。以前面簡單的 HTML 頁面為例,單擊<div>元素會按照如下圖所示順序觸發事件。
DOM事件流
在 DOM 事件流中,實際的目標(<div>元素)在捕獲階段不會接收到事件。這意味著在捕獲階段, 事件從 document 到<html>再到<body>后就停止了。下一個階段是“處于目標”階段,于是事件在<div> 上發生,并在事件處理(后面將會討論這個概念)中被看成冒泡階段的一部分。然后,冒泡階段發生, 事件又傳播回文檔。
多數支持 DOM 事件流的瀏覽器都實現了一種特定的行為;即使“DOM2 級事件”規范明確要求捕 獲階段不會涉及事件目標,但 IE9、Safari、Chrome、Firefox 和 Opera 9.5 及更高版本都會在捕獲階段觸 發事件對象上的事件。結果,就是有兩個機會在目標對象上面操作事件。
之后我們講解事件處理順序。
文章參考《JavaScript高級程序設計》(第三版)。
件流:
事件冒泡
取消冒泡:oEvent.cancelBubble=true
<html>
<head>
<meta charset="utf-8">
<title>無標題文檔</title>
<style>
#div1 {width:400px; height:300px; background:#CCC; display:none;}
</style>
<script>
window.onload=function ()
{
var oBtn=document.getElementById('btn1');
var oDiv=document.getElementById('div1');
oBtn.onclick=function (ev)
{
var oEvent=ev||event;
oDiv.style.display='block';
//alert('按鈕被點擊了');
oEvent.cancelBubble=true; //取消事件冒泡,是解決許多問題的方法和手段
};
document.onclick=function ()
{
oDiv.style.display='none';
//alert('document被點擊了');
};
};
</script>
</head>
<body>
<input id="btn1" type="button" value="顯示" />
<div id="div1">
</div>
</body>
</html>
冒泡型事件:
<html>
<head>
<title>冒泡型事件</title>
<script language="javascript">
function add(sText){
var oDiv=document.getElementById("display");
oDiv.innerHTML +=sText; //輸出點擊順序
}
</script>
</head>
<body onclick="add('body<br>');">
<div onclick="add('div<br>');">
<p onclick="add('p<br>');">Click Me</p>
</div>
<div id="display"></div>
</body>
</html>
執行順序:p對象 -> div對象 -> body對象
冒泡型事件執行順序::由內到外(p -> div -> body -> document)
注意: DOM 0級只有冒泡, 沒有捕獲
捕獲型事件
相對于IE使用冒泡型事件, Netscape使用了另一種稱為捕獲型事件(eventcapturing)的解決方案;
addEventListener(事件名稱,函數, bCapture)
removeEventListener(事件名稱, 函數, bCapture)
事件監聽函數第三個參數bCapture確定是冒泡型還是捕獲型事件(true:捕獲 false:冒泡,默認值false)
<!DOCTYPE html>
<html>
<head>
<style>
div {
background-color: coral;
border: 1px solid;
padding: 50px;
}
</style>
</head>
<body>
<div id="myDiv2">
<p id="myP2">點擊該段落, 我是捕獲</p>
</div>
<script>
document.getElementById("myP2").addEventListener("click", function() {
alert("你點擊了 P 元素!");
}, true);
document.getElementById("myDiv2").addEventListener("click", function() {
alert("你點擊了 DIV 元素!");
}, true);
</script>
</body>
</html>
執行順序: div對象 -> p對象
捕獲型事件執行順序:由外到內(如:document -> body -> div -> p)
冒泡型:事件從內部往外部依次執行。
捕捉型:事件從外部往內部依次執行。
事件監聽
通用監聽方法:
1.直接在HTML標簽中分配事件處理函數:
<script language="javascript">
function add(sText){
var oDiv=document.getElementById("display");
oDiv.innerHTML +=sText; //輸出點擊順序
}
</script>
</head>
<body onclick="add('body<br>');">
<div onclick="add('div<br>');">
<p onclick="add('p<br>');">Click Me</p>
</div>
<div id="display"></div>
</body>
2.結構與行為的分離:
<html>
<head>
<title>監聽函數</title>
<script language="javascript">
window.onload=function(){
var oP=document.getElementById("myP"); //找到對象
oP.onclick=function(){ //設置事件監聽函數
alert('我被點擊了');
}
}
</script>
</head>
<body>
<div>
<p id="myP">Click Me</p>
</div>
</body>
</html>
事件監聽的作用:
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>無標題文檔</title>
<script>
window.onload=function ()
{
alert('a');
};
window.onload=function ()
{
alert('b');
};
</script>
</head>
<body>
</body>
</html>
以上程序只彈出alert('b');
理解:對同一對象執行兩次事件(同一事件類型)處理函數時,往往只能只執行后一個
因此如果要讓腳本在本瀏覽器中正常運行的話,就必須使用瀏覽器所支持的事件監聽器
IE中的監聽方法:
attachEvent(事件名稱, 函數), 綁定事件處理函數 attach: 貼上, 附著
detachEvent(事件名稱, 函數), 解除綁定 detach: 分離, 拆開
注意:IE只支持冒泡型事件監聽, 沒有第三個參數, 事件名稱前要加"on";
<html>
<head>
<title>多個監聽函數</title>
<script language="javascript">
function fnClick1(){
alert("我被fnClick1點擊了");
}
function fnClick2(){
alert("我被fnClick2點擊了");
//oP.detachEvent("onclick",fnClick1); //刪除監聽函數1
}
var oP;
window.onload=function(){
oP=document.getElementById("myP"); //找到對象
oP.attachEvent("onclick",fnClick1); //添加監聽函數1
oP.attachEvent("onclick",fnClick2); //添加監聽函數2
}
</script>
</head>
<body>
<div>
<p id="myP">Click Me</p>
</div>
</body>
</html>
標準DOM的事件監聽:
addEventListener(事件名稱,函數, 捕獲)
element.addEventListener(event, function, useCapture)
removeEventListener(事件名稱, 函數, 捕獲)
element.removeEventListener(event, function, useCapture)
bCapture 是用于冒泡階段還是捕獲階段(true:捕獲 false:冒泡,默認值false)
注意:IE9版本已支持
<html>
<head>
<title>標準DOM的事件監聽</title>
<script language="javascript">
function fnClick1(){
alert("我被fnClick1點擊了");
//oP.removeEventListener("click",fnClick2,false); //刪除監聽函數2
}
function fnClick2(){
alert("我被fnClick2點擊了");
}
var oP;
window.onload=function(){
oP=document.getElementById("myP"); //找到對象
oP.addEventListener("click",fnClick1,false); //添加監聽函數1
oP.addEventListener("click",fnClick2,false); //添加監聽函數2
}
</script>
</head>
<body>
<div>
<p id="myP">Click Me</p>
</div>
</body>
</html>
編寫兼容性事件監聽函數
function addEvent(obj, ev, fn){
if(obj.addEventListener){
obj.addEventListener(ev, fn, false);
}else{
obj.attachEvent('on'+ev, fn);
}
}
function removeEvent(obj, ev, fn){
if(obj.removeEventListener){
obj.addEventListener(ev, fn, false);
}else{
obj.attachEvent('on'+ev, fn);
}
}
實例:
#JavaScript#
事件流就是多個節點對象對同一個事件進行響應的先后順序。
1.冒泡型
事件從上向下進行響應,稱冒泡
實例1.含五層嵌套的Div標簽,當點擊Div事件時,對象邊框邊紅色,并抓取標簽名。
代碼演示
瀏覽結果
點擊click事件,從內到外一次響應。
完整代碼
*請認真填寫需求信息,我們會在24小時內與您取得聯系。