事件流指從頁面中接收事件的順序。jquery
1.事件冒泡(經常使用)瀏覽器
IE中採用的事件流是事件冒泡,先從具體的接收元素,而後逐步向上傳播到不具體的元素。app
2.事件捕獲(少用)函數
Netscapte採用事件捕獲,先由不具體的元素接收事件,最具體的節點最後才接收到事件。性能
3.DOM事件流測試
DOM2級事件包括三個階段:事件捕獲階段、處於目標階段和事件冒泡階段。this
事件處理程序就是響應某些事件的函數,如onclick等。spa
1. DOM0級事件處理程序3d
每一個元素都有本身的事件處理程序屬性,如onclick等。能夠經過js將一個函數賦值給元素的事件處理程序屬性。指針
在DOM0事件處理程序中,事件處理程序裏的this指向當前元素。
var objlogo=document.getElementById("site_nav_top"); objlogo.onclick=function(){ alert(this.innerHTML);//代碼改變世界 }
刪除DOM0事件,只需將事件處理程序的值賦爲null便可。
objlogo.onclick=null;
2. DOM2級事件處理程序
DOM2有兩個方法用來添加和移除事件處理程序:addEventListener()和removeEventListener()。它們都有三個參數:第一個參數是事件名(如click);第二個參數是事件處理程序函數;第三個參數若是是true則表示在捕獲階段調用,爲false表示在冒泡階段調用。
//不能移除 var obj = document.getElementById('site_nav_top');
obj.addEventListener('click', function () {
alert(this.innerHTML);
}, false);
obj.removeEventListener('click', function () {
alert(this.innerHTML);
}, false);
//能移除 var obj=document.getElementById("site_nav_top"); var show=function(){ alert(this.innerHTML); } obj.addEventListener("click",show,false); obj.removeEventListener("click",show,false);
3.IE事件處理程序
IE的事件處理程序也有兩個相似的方法:attachEvent()和detachEvent()。它們有兩個參數:第一個是事件名(如onlick);第二個參數是事件處理程序的函數。
注意:
var obj=document.getElementById("site_nav_top"); var show=function(){ alert(obj.innerHTML); } obj.attachEvent("onclick",show); obj.detachEvent("onclick",show);
4.跨瀏覽器的事件處理程序
綜合前面幾種狀況,進行瀏覽器能力檢測,就能夠寫出跨瀏覽器的事件處理程序了.
EventUtil = { addHandler: function (obj, event, handler) { if (obj.addEventListener) { obj.addEventListener(event, handler, false); } else if (obj.attachEvent) { obj.attachEvent('on' + event, handler); } else { obj['on' + event] = handler; } }, removeHandler: function (obj, event, handler) { if (obj.removeEventListener) { obj.removeEventListener(event, handler, false); } else if (obj.detachEvent) { obj.detachEvent('on' + event, handler); } else { obj['on' + event] = null; } } };
var obj = document.getElementById('site_nav_top'); var show = function () { alert(obj.innerHTML); } EventUtil.addHandler(obj, 'click', show); EventUtil.removeHandler(obj, 'click', show);
當觸發DOM事件時,會產生一個事件對象event。不一樣瀏覽器對該對象的支持略有不一樣。
1.DOM中的事件對象
在支持DOM0或DOM2的瀏覽器中,會將event對象傳入到事件處理程序中。
var obj=document.getElementById("site_nav_top"); var show=function(event){ alert(event.type); } obj.addEventListener("click",show,false);//點擊運行結果 click
event對象包含於建立它的事件對象相關的屬性和方法。幾種經常使用屬性和方法:
① this, currentTarget 與 target:
event.this與event.currentTarget始終相等,表示事件處理程序當前正在處理的元素;
event.target表示事件的實際目標元素。
var obj=document.getElementById("site_nav_top"); var show=function(event){ console.log(this); console.log(event.currentTarget); console.log(event.target); } obj.addEventListener("click",show,false); //點擊頭部「代碼改變世界」結果 <div id="site_nav_top">,<div id="site_nav_top">,<div id="site_nav_top"> var show=function(event){ console.log(this); console.log(event.currentTarget); console.log(event.target); } document.body.addEventListener("click",show,false); //點擊頭部「代碼改變世界」結果: <body>, <body>, <div id="site_nav_top">
②event.type:被觸發的事件類型,如click。經過判斷該屬性,能夠用一個函數中處理多個事件。
var obj=document.getElementById("nav_menu"); var handler=function(event){ switch(event.type){ case "mouseover": event.target.style.backgroundColor="red"; break; case "mouseout": event.target.style.backgroundColor=""; break; case "click": alert("click menu"); break; } } obj.addEventListener("click",handler,false); obj.addEventListener("mouseover",handler,false); obj.addEventListener("mouseout",handler,false);
③event.preventDefault():阻止事件的默認行爲。
例如在上面的例子中,單擊站點導航條在彈出「click menu」後,仍然打開了連接。若是想阻止其默認行爲,能夠這樣處理:
case "click": alert('click menu') event.preventDefault(); break;
④event.stopPropagation():阻止事件進一步冒泡或捕獲。
var obj = document.getElementById('nav_menu'); var handler = function (event) { alert('handler'); } var handler1 = function (event) { alert('handler1'); } obj.addEventListener('click', handler, false); document.body.addEventListener('click', handler1, false);
在這個例子中給菜單和body分別添加了單擊事件,當點擊菜單時會出現兩次彈窗。若是想阻止事件冒泡,能夠作以下修改:
var handler=function(event){ alert('handler'); event.stopPropagation(); }
2. IE中的事件對象
①event對象
使用DOM0添加的事件處理程序,event做爲window對象的屬性存在。
var obj=document.getElementById("nav_menu"); obj.onclick=function(event){ alert(window.event.type); }
使用attachEvent添加的事件處理程序,能夠將event做爲函數的參數傳入,也能夠直接使用window.event。
var obj=document.getElementById("nav_menu"); obj.attachEvent("onclick",function(event){ alert(event.type); alert(window.event.type); });
②event.srcElement:事件的目標元素,等同於DOM中的target屬性。
③event.returnValue:將該屬性設置爲false能夠阻止默認事件。至關於DOM中的preventDefault()。
④event.cancelBubble:將該屬性設爲true能夠阻止事件冒泡。至關於DOM中的 stopPropagation()。
3.跨瀏覽器的事件對象
綜合考慮DOM和IE中的事件對象,寫出跨瀏覽器的事件對象,放在以前的EventUtil中。
EventUtil = { addHandler: function (obj, event, handler) { ...... }, removeHandler: function (obj, event, handler) { ...... }, getEvent: function (event) { return event ? event : window.event; }, getTarget: function (event) { return event.target || event.srcElement; }, preventDefault: function (event) { if (event.preventDefault) { event.preventDefault(); } else { event.returnValue = false; } }, stopPropagation: function (event) { if (event.stopPropation) { event.stopPropation(); } else { event.cancelBubble = true; } } }; //以園子首頁菜單欄爲例調用 var obj = document.getElementById('nav_menu'); EventUtil.addHandler(obj, 'click', function (event) { var event = EventUtil.getEvent(event); var target = EventUtil.getTarget(event); alert(target); EventUtil.preventDefault(event); EventUtil.stopPropagation(event); }); EventUtil.addHandler(document.body, 'click', function () { alert('body'); })
1.load事件
load能夠用來判斷圖片加載完畢。注意:新建立的圖像元素不是在加載到頁面中才開始下載,而是設置src以後就開始下載。
var obj = document.getElementById('site_nav_top'); EventUtil.addHandler(obj, 'click', function () { var img = new Image(); EventUtil.addHandler(img, 'load', function () { alert('load'); }); img.src = 'http://static.cnblogs.com/images/logo_small.gif'; obj.appendChild(img); })
load能夠用來判斷js加載完成。<script>元素能夠觸發load事件,來判斷動態加載的js文件是否加載完成。它和img不一樣,必須設置了src屬性而且添加到文檔以後纔會開始下載。
EventUtil.addHandler(document.body,"click",function(){ var script=document.createElement("script"); EventUtil.addHandler(script,"load",function(){ alert('load'); }); script.src="http://common.cnblogs.com/script/jquery.js"; document.body.appendChild(script); })
2.resize事件:當瀏覽器的寬度或高度變化時觸發該事件。有些瀏覽器窗口變化1像素時就觸發該事件,有的瀏覽器在中止調整窗口大小時纔出發該事件。所以不要在該方法中寫大量的計算代碼,以避免減緩瀏覽器速度。
3.獲取鼠標位置
var obj = document.getElementById('headline_block'); EventUtil.addHandler(obj, 'click', function (event) { var result = event.clientX + ',' + event.clientY + '\r\n'; result += event.pageX + ',' + event.pageY+'\r\n'; result+=event.screenX+','+event.screenY; alert(result); })
4.beforeunload事件
事件在瀏覽器卸載頁面以前觸發,能夠經過它來取消卸載並繼續使用原來的頁面。
要在卸載頁面時顯示彈窗提示,須要將event.returnValue設置爲提示語,而且將該提示語做爲函數的返回值。
EventUtil.addHandler(window,'beforeunload',function(event){ event=EventUtil.getEvent(event); var msg='確認關閉嗎'; event.returnValue=msg; return msg; });
1.事件委託
事件委託能夠解決頁面中事件處理程序過多的問題。事件委託利用了事件冒泡,只指定一個事件處理程序,就能夠處理某一類型的全部事件。
EventUtil.addHandler(document.body, 'click', function (event) { event = EventUtil.getEvent(event); var target = EventUtil.getTarget(event); switch (target.id) { case 'site_nav_top': alert('口號'); break; case 'nav_menu': alert('點擊菜單'); EventUtil.preventDefault(event); break; case 'editor_pick_lnk': alert('推薦區'); EventUtil.preventDefault(event); break; } });
2.移除事件處理程序
若是內存中保留大量無用的事件處理程序,會影響性能。因此必定要在不須要的時候及時移除事件處理程序。尤爲注意如下狀況:
使用innerHTML刪除帶有事件處理程序的元素時,要先將事件處理程序設置爲null。使用委託也能夠解決這個問題,不直接將事件加載會被innerHTML替換的元素,而是將事件賦給其父元素,這樣就能夠避免了。
卸載頁面時,最好手工清除全部的事件處理程序。
1. DOM中的事件模擬分三步:
2. 模擬鼠標事件
首先createEvent()方法傳入參數是「MouseEvent」來模擬鼠標事件。
返回的event對象有一個initMouseEvent()方法,用來初始化事件信息。該方法有15個參數:
最後給DOM元素調用dispatchEvent()方法來觸發事件。
//執行位置博客園首頁 var objmenu = document.getElementById('nav_menu'); objmenu.onclick = function () { console.log('menu'); } document.body.onclick = function () { console.log('body'); } var event = document.createEvent('MouseEvent'); event.initMouseEvent('click', true, true, document.defaultView, 0, 0, 0, 0, 0, false, false, false, false, 0, null); for (var i = 0; i < 5; i++) { objmenu.dispatchEvent(event); }
3. 自定義DOM事件
DOM3中支持自定義DOM事件。要建立新的自定義事件,能夠調用document.createEvent()方法,返回的對象有一個initCustomEvent()方法,包含四個參數:
最後在DOM元素調用dispatchEvent()方法觸發事件。
var objmenu = document.getElementById('nav_menu'); EventUtil.addHandler(objmenu, 'myevent', function (event) { console.log('menu' + event.detail); }); EventUtil.addHandler(document.body, 'myevent', function (event) { console.log('body' + event.detail); }) if (document.implementation.hasFeature('CustomEvents', '3.0')) { var event = document.createEvent('CustomEvent'); event.initCustomEvent('myevent', true, true, '測試事件detail'); for (var i = 0; i < 5; i++) { objmenu.dispatchEvent(event); } }