一. 事件
-
事件的三個階段:事件捕獲 -> 事件目标 -> 事件冒泡
捕獲階段:先由文檔的根節點document往事件觸發對象,從外向内捕獲事件對象;
目标階段:到達目标事件位置(事發地),觸發事件;
冒泡階段:再從目标事件位置往文檔的根節點方向回溯,從内向外冒泡事件對象
-
事件捕獲:事件發生時首先發生在document上,然後依次傳遞給body,最後到達目的節點(即事件目标),事件流模型:div →body→ html→ document 。
圖示說明:
在js中事件冒泡的了解分析 -
事件冒泡:事件到達事件目标之後不會結束,會逐層向上冒泡,直至document對象,跟事件捕獲相反。
圖示說明:
在js中事件冒泡的了解分析 -
onclick 事件冒泡,重寫onlick會覆寫之前屬性,沒有相容性問題
addEventListener(event.type, handle, boolean); IE8及以下不支援,屬于DOM2級的方法,可添加多個方法不被覆寫。事件類型沒有on,第三個參數false,表示在事件第三階段(冒泡)觸發,true表示在事件第一階段(捕獲)觸發。如果綁定同一個事件同一個方法,隻會執行一次,是以如果handle是同一個方法,隻執行一次。
attachEvent(event.type, handle ); IE特有,相容IE8及以下,可添加多個事件處理程式,隻支援冒泡階段,可以多次進行綁定,是以如果handle是同一個方法,綁定幾次執行幾次,同時事件類型要加on。
預設事件行為:href="" target="_blank" rel="external nofollow" 連結,submit表單送出等
-
阻止預設事件:
return false; 阻止獨享屬性(通過on這種方式)綁定的事件的預設事件,阻止浏覽器對事件的預設處理,隻在目前函數有效,不會影響其他外部函數的執行
event.preventDefault( ); 阻止通過 addEventListener( ) 添加的事件的預設事件
event.returnValue = false; 阻止通過 attachEvent( ) 添加的事件的預設事件
-
事件的綁定與事件的解綁
事件的綁定:
代碼如下:
function addEvent(element,eType,handle,bol){
// 支援addEventListener
if(element.addEventListener){
element.addEventListener(eType,handle,bol);
// 支援attachEvent
}else if(element.attachEvent){
element.attachEvent("on"+eType,handle);
// 相容的onclick的綁定
}else{
element["on"+eType] = handle;
}
}
事件的解綁:
代碼如下:
function removeEvent(element,eType,handle,bol){
// 支援addEventListener
if(element.addEventListener){
element.addEventListener(eType,handle,bol);
// 支援attachEvent
}else if(element.attachEvent){
element.detachEvent("on"+eType,handle);
// 相容的onclick的綁定
}else{
element["on"+eType] = null;
}
}
封裝函數:通過事件冒泡的方式,相容事件捕獲隻需要添加個bool參數
代碼如下:
var EventUtil = {
addEvent: function(element,type,handle){
if(element.addEventListener){
element.addEventListener(type,handle,false);
}else if(element.addEvent){
element.addEvent("on"+type,handle);
}else{
element["on"+type] = handle;
}
},
removeEvent:function(element,type,handle){
if(element.removeEventListener){
element.removeEventListener(type,handle,false);
}else if(element.removeEvent){
element.removeEvent("on"+type,handle);
}else{
element["on"+type] = null;
}
}
}
-
常見的事件綁定
1)bind()
隻能給調用它的時候已經存在的元素綁定事件,不能給未來新增的元素綁定事件
bind()不能使用的情況:為DOM中的很多元素綁定相同的事件,為DOM中的尚不存在的元素綁定事件
2)live()
方法會把click事件綁定到(document)對象,而且隻需要給(document)綁定一次,然後就能夠處理後續動态加載的節點的事件
在接收到任何事件時,(document)對象都會檢查事件類型和事件目标,如果是click事件且事件目标是td,那麼就執行委托給它的處理程式
3)delegate()
直接将目标元素選擇符(“td”)、事件(“click”)及處理程式與“受拖方”("#info_table")綁定,不額外收集元素、事件傳播路徑縮短、語義明确
支援在連綴的DOM周遊方法後面調用
-
事件冒泡、事件捕獲阻止
event.stopPropagation( ); 阻止事件的進一步傳播,包括(冒泡,捕獲),無參數
event.cancelBubble = true; true 為阻止冒泡
-
W3C事件模型中發生的任何事件,先從其祖先元素window開始一路向下捕獲, 直到達到目标元素,其後再次從目标元素開始冒泡。可以決定事件處理器是注冊在捕獲或者是冒泡階段。
注意:如果addEventListener的最後一個參數是true, 那麼處理函數将在捕獲階段被觸發; 否則(false), 會在冒泡階段被觸發,預設false。
二、事件冒泡
- 事件冒泡:當一個元素接收到事件的時候 會把他接收到的事件傳給自己的父級,一直到window。從事件源,自下而上的過程中,阻止向上冒泡,即阻止觸發上級元素的事件觸發,上級元素做事件觸發時,在此事件源上無效。在事件傳播的過程中,當事件在一個元素上出發之後,事件會逐級傳播給先輩元素,直到document為止,有的浏覽器可能到window為止。
-
事件冒泡的執行個體
代碼如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>事件冒泡</title>
</head>
<body>
<div id="div1">div1
<div id="div2">div2</div>
</div>
</body>
<script>
var div1 = document.getElementById("div1");
var div2 = document.getElementById("div2");
div1.onclick = function(){
console.log("我是div1");
};
div2.onclick = function(){
console.log("我是div2");
};
</script>
</html>
說明:兩個父子關系的div1和div2,分别給div1和div2綁定了點選事件。當點選div1的時候,控制台列印輸出 我是div1。當點選div2的時候,控制台列印輸出 我是div2 和 我是div1,在這個時候就說明了當我們子點選div2的時候,div1的事件也被觸發了,父級事件被觸發,這種現象相當于就是冒泡事件。
-
取消事件冒泡的方式:
标準的W3C 方式:e.stopPropagation();這裡的stopPropagation是标準的事件對象的一個方法,調用即可
非标準的IE方式:ev.cancelBubble=true; 這裡的cancelBubble是 IE事件對象的屬性,設為true就可以了
封裝取消事件冒泡的函數:
代碼如下:
function stopBubble(env){
// 如果提供事件對象,說明為非IE浏覽器
if(env && env.stopPropagation){
env.stopPropagation();
}else{
// IE浏覽器
window.event.cancelBubble = true;
}
}
-
取消事件冒泡的執行個體:
代碼如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>事件冒泡2</title>
<style>
.d1 {
width: 300px;
height: 300px;
background-color: skyblue;
display: none;
}
</style>
</head>
<body>
<button id="btn">按鈕</button>
<div class="d1"></div>
</body>
<script>
// 單擊動作會從btn傳到document中,發生事件冒泡
var btn = document.getElementById("btn");
var d1 = document.getElementsByClassName("d1")[0];
// 點選按鈕的時候,元素d1顯示
btn.onclick = function(e){
d1.style.display = "block";
// 阻止冒泡
stopBubble(e);
};
// 點選網頁其它地方的時候,元素d1隐藏
document.onclick = function(){
d1.style.display = "none";
};
// 阻止浏覽器的預設行為函數,事件冒泡
// event.stopPropagation 阻止事件冒泡的方法
function stopBubble(e) {
// 非IE浏覽器阻止冒泡
if( e && e.stopPropagation )
e.stopPropagation();
else
// IE浏覽器阻止冒泡
window.event.cancelBubble = true;
}
</script>
</html>
說明:定義一個按鈕,在按鈕下面有一個div的元素d1,預設為隐藏。點選按鈕的時候,元素d1顯示。在點選按鈕的時候,調用了阻止事件冒泡的發生函數stopBubble()。點選docume網頁其它地方的時候,元素d1隐藏。
三、跨浏覽器的事件對象
-
跨浏覽器的事件對象
代碼如下:
var EventUtil={
getEvent:function(event){
return event||window.event;
},
getTarget:function(event){
return event.target||event.srcElement;
},
preventDefault:function(){
if(event.preventDefault){
event.preventDefault();
}else{
event.returnValue=false;
}
},
stopPropagation:function(){
if(event.stopPropagation){
event.stopPropagation();
}else{
event.cancelBubble=true;
}
},
addEvent:function(element,type,handler){
if(element.addEventListener){
element.addEventListener(type,handler,false);
}else if(element.attachEvent){
element["e"+type]=function(){
handler.call(element)
}
element.attachEvent("on"+type,element["e"+type]);
}else{
element["on"+type]=handler;
}
},
removeEvent:function(element,type,handler){
if(element.removeEventListener){
element.removeEventListener(type,handler,false);
}else if(element.detachEvent){
element.detachEvent("on"+type,element["e"+type]);
element["e"+type]=null;
}else{
element["on"+type]=null;
}
}
};