事件流:
事件流:頁面接收事件的順序。
IE定義的:事件冒泡流(由最具體的元素依次傳播到DOM樹的最上層的Document)
NetScape定義的:事件捕獲流(由不具體的節點依次傳播到具體的節點)
DOM事件流:先是捕獲階段,然后是處理目標階段,最后是事件冒泡階段。
事件處理程序:
a. HTML事件處理程序:
在HTML中加入事件代碼:
事件中的代碼可以在獨立的JS中,事件代碼在執行時,有權訪問全局作用域中的任何代碼。
缺點:
1.時差問題:
在JS程序還沒有具備執行條件時,就執行了事件,這時會出現錯誤。
2.耦合問題:
HTML與JS代碼緊密耦合,使得修改時需要對兩者都進行修改。
3.JS引擎不同:
不同的JS引擎對其作用域的擴展方式解析不同,在訪問非限定對象成員時會出錯。、
b.DOM0級事件處理程序:
每個元素都有自己的事件處理程序屬性。
var btn=document.getElementById("click");
btn.onclick=function () {
alert("clicked")
};
DOM0級是元素的方法,因此,事件處理程序是在元素的作用域中執行,程序中的this指向該元素。
該程序會在事件冒泡階段被處理。
如何取消:btn.onclick=null;
c.DOM2級處理程序:
定義了兩個方法:addEventListener()removeEventListener()
3個參數:事件名、事件處理程序的函數、布爾值(true事件捕獲階段處理,false事件冒泡階段處理)
btn.addEventListener("click",function () {
alert("clicked")
},false);
優點:可以對同一元素定義多個事件,事件會順序處理
btn.addEventListener("click",function () {
alert("clicked")
},false);
btn.addEventListener("click",function () {
alert(this.id);
},false);
注意:一般在事件冒泡階段處理,這樣可以最大程度兼容瀏覽器。
刪除事件:
利用addEventListener()定義的事件處理程序只能通過removeEventListener()刪除。
d. IE事件處理程序(IE Opera)
兩個方法:attachEvent()detachEvent(),兩個參數:事件類型、事件處理函數
注意:事件處理程序的作用域為全局作用域,而非元素的作用域。所以this為window。
可以定義多個事件處理程序,不過執行順序相反。
var handler=function () {
alert("clicked")
};
btn.attachEvent("onclick",handler);
btn.detachEvent("onclick",handler);
e.跨瀏覽器的事件處理程序
利用能力檢測對瀏覽器進行測試,分為三種情況:DOM2級、IE、DOM0級
主要方法:
設置一個對象EventUtil,該對象中保存兩個屬性:addHandler和removeHandler,兩個屬性對三種情況進行分類:
var EventUtil={
addHandler:function (element,type,handler) {
if(element.addEventListener){
element.addEventListener(type,handler,false);
}
elseif(element.attachEvent){
element.attachEvent("on"+type,handler);
}
else{
element["on"+type]=handler;
}
},
removeHandler:function (element,type,handler) {
if(element.removeEventListener){
element.removeEventListener(type,handler,false)
}
elseif(element.detachEvent){
element.detachEvent("on"+type,handler)
}
else{
element["on"+type]=null;
}
}
};
調用:
var btn=document.getElementById("button");
var handler=function () {
alert("clicked")
};
EventUtil.addHandler(btn,"click",handler);
EventUtil.removeHandler(btn,"click");
事件對象:event
a. DOM中的事件對象
兼容DOM的瀏覽器會將event對象傳入到事件處理程序中。無論事件處理程序使用的是DOM0還是DOM2級。
var btn=document.getElementById("btn");
btn.onclick=function (event) {
alert(event.type)
};
btn.addEventListener("click",function (event) {
alert(event.type)
},false);
在需要一個事件處理函數處理多個事件時,可以使用type類型,利用switch語句進行指定。
b. IE中的事件對象
1.訪問IE中的event方法:
DOM0:window.event
var btn=document.getElementById("btn");
btn.onclick=function () {
var event=window.event;
alert(event.type)
};
2.其他的DOM2IEHTML事件處理程序可以使用event。
c.跨瀏覽器中的事件對象
在上述的EventUtil對象中加入更多的屬性
var EventUtil={
addHandler:function (element,type,handler) {
if(element.addEventListener){
element.addEventListener(type,handler,false);
}
else if(element.attachEvent){
element.attachEvent("on"+type,handler);
}
else{
element["on"+type]=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.stopPropagation){
event.stopPropagation();
}
else {
event.cancelBubble=true;
}
},
removeHandler:function (element,type,handler) {
if(element.removeEventListener){
element.removeEventListener(type,handler,false)
}
else if(element.detachEvent){
element.detachEvent("on"+type,handler)
}
else{
element["on"+type]=null;
}
}
};
使用:
先取得event,再使用其它屬性。
varbtn=document.getElementById("btn");
btn.onclick=function (event) {
varevent=EventUtil.getEvent(event);
EventUtil.getEvent(event);
};
事件類型
一:UI事件:
UI不一定與用戶操作有關。
1.load事件:
頁面完全加載完畢后觸發。也可以在圖像元素上觸發。
EventUtil.addHandler(window,"load",function (event) {
alert("加載完畢");
})
2.unload事件:
頁面被完全卸載后觸發,如頁面切換。
3.resize事件:
瀏覽器窗口被調整到一個新的高度和寬度時觸發。
EventUtil.addHandler(window,"resize",function (event) {
alert("調整高度");
})
4.scroll事件:
元素被滾動時觸發
二:焦點事件:
最主要的是focus(元素獲得焦點時觸發)和blur(元素失去焦點時觸發)
三:鼠標與滾輪事件:
9個鼠標事件:
click
mousedown
mouseup
mousemove
mouseenter
mouseleave
mouseout
mouseover
dbclick
1.客戶區坐標位置:clientX
clientY
在瀏覽器視口中的位置(不加滾輪)
在瀏覽器視口中的位置(不加滾輪)
2.頁面坐標位置: pageX pageY
在頁面中的位置(加上滾輪)
3.屏幕坐標位置:screenX screenY
相對于電腦屏幕的位置,頁面放大縮小也是相對于電腦屏幕
var
div=document.getElementsByTagName("div")[0];
EventUtil.addHandler(div,"click",function
(event) {
var
event=EventUtil.getEvent(event);
alert("CLIENTX:"+event.clientX+"screenX:"+event.screenX);
})
相關元素:
只有mouseover和mouseout才有的屬性:
relatedTarget, IE中是fromElement和toElement,
其他
事件該屬性為null
對于mouseover,相關元素是失去光標的元素,對于mouseout,相關元素是獲得光標的元
素
var
div=document.getElementsByTagName("div")[0];
EventUtil.addHandler(div,"mouseover",function
(event) {
var
event=EventUtil.getEvent(event);
var
target=EventUtil.getTarget(event);
var
related=EventUtil.getRelatedTarget(event);
alert("相關元素:"+event.tagName+"鼠標移入:"+related.tagName);
})
鼠標按鈕:
對mousedown和mouseup事件,在其event對象中有button屬性
DOM中button屬性有3個值:0(左鍵),1(滾輪),2(右鍵)
IE中的有8個值,0-7,這么多是沒有意義的,用戶很少同時按幾個鍵,所以需要將其轉換為
0,1,2即可。
在EventsUtil對象中加入getButton屬性
"getButton":function
(event) {
if(document.implementation.hasFeature("MouseEvents","2.0")){
return event.button;
}
else{
switch (event.button){
case 0:
case 1:
case 3:
case 5:
case 7:
return 0;
case 4:
return 1;
case 2:
case 6:
return 2;
return 2;
}
}
}
var div=document.getElementsByTagName("div")[0];
EventUtil.addHandler(div,"mousedown",function
(event) {
var event=EventUtil.getEvent(event);
var button=EventUtil.getButton(event);
alert("button屬性值:"+button);
})
鼠標滾輪事件:
mousewheel事件:其event對象中包含wheelDelta屬性,wheelDelta是120的倍數,向前是正
值,向后是負值。
特殊情況:
Opera
9.5之前的版本中,正負號顛倒。
FireFox中的該事件名稱為DOMMouseScroll,其屬性為detail,detail是3的倍數,向前是負
值,向后是正值。
四:鍵盤與文本事件:
3個鍵盤事件:
Keydown:按下任意鍵觸發
Keypress:按下字符鍵觸發,可以影響文本顯示的鍵也會觸發(如退格鍵)
keyup:釋放鍵觸發
鍵盤上的每個鍵都有對應的鍵碼,其對應的屬性為keyCode
textInput事件:DOM3中新增的替代keypress的事件。與keypress的不同:只有在可編輯區
域可以觸發textInput事件,并且只有能夠輸入實際字符的鍵才能觸發。
復合事件:
針對同時按住多個鍵輸出的字符。
變動事件:
DOM2級的變動事件處理的是DOM中的變化。比如刪除節點、插入節點時的變化。
五:HTML5事件:瀏覽器自定義的事件
contextmenu事件:上下文菜單(通過鼠標右擊實現)
點擊我看菜單
百度
必應
天貓
EventUtil.addHandler(window,"load",function
(event) {
vardiv=document.getElementById("myDiv");
EventUtil.addHandler(div,"contextmenu",function (event) {
event=EventUtil.getEvent(event);
EventUtil.preventDefault(event);
varmenu=document.getElementById("Menu");
menu.style.left=event.clientX+"px";
menu.style.top=event.clientY+"px";
menu.style.visibility="visible";
})
EventUtil.addHandler(document,"click",function (event) {
document.getElementById("Menu").style.visibility="hidden";
})
})
beforeunload事件:當用戶關閉該頁面時觸發對話框,讓用戶選擇是否離開頁面。
DOMContentLoaded事件:形成DOM樹之后即可觸發,而不用等待CSS、JS等的加載。
readystatechange事件:提供與文檔或者元素的加載狀態有關的信息。可用于加載外部JS和CSS。
pageshow和pagehide事件:在用戶使用瀏覽器的后退和前進時加快頁面的轉換速度。
haschange事件:在URL的參數列表發生變化時通知開發人員。(在AJAX應用中,開發人員經常利用URL的參數列表保存狀態)
六:設備事件:智能手機、平板電腦
orientationchange事件:屏幕的橫向與縱向
window.orientation屬性包括3個值:
0肖像模式
90向左旋轉
-90向右旋轉
MozOrientation事件:平面方向的變化。
deviceorientation事件:xyz發生變化
devicemotion事件:檢測設備是否往下掉,是否被走著的人拿在手里。
七:觸摸與手勢事件:
觸摸事件:
touchstart
touchmove
touchend
touchcancel
手勢事件:兩個手指觸摸屏幕時觸發
gesturestart
gesturechange
gestureend
內存和性能
添加大量的事件處理程序會導致頁面的整體運行性能,主要原因為:
1.大量的事件處理程序就會有大量的函數,每個函數都是一個對象,會占用大量的內存。
2.需要事先指定DOM訪問次數,延遲了頁面的交互就緒事件。
處理方法:
1.事件委托:利用了事件冒泡
原方法:
var item1=document.getElementsByTagName("li")[0];
var item2=document.getElementsByTagName("li")[1];
var item3=document.getElementsByTagName("li")[2];
EventUtil.addHandler(item1,"click",function
(event) {
location.,function
(event) {
location.,function
(event) {
location.,function
(event) {
event=EventUtil.getEvent(event);
vartarget=EventUtil.getTarget(event);
switch(target.id){
case"baidu":
location.;
break;
}
})
不是所有的事件都適合事件委托方式,適合的事件有:clickmousedown mouseupkeydown keyupkeypress
2.移除事件處理程序
當不需要事件時,需要進行事件處理程序的移除。
哪些情況不需要事件:
a.從文檔中移除了帶有事件處理程序的元素。
b.將帶有事件處理程序的元素被innerHTML刪除。
此時應該將事件設為null,btn.onclick=null;
模擬事件:利用JS來觸發而非用戶操作或者瀏覽器功能。
1.DOM中的事件模擬
a.模擬鼠標事件
b.模擬鍵盤事件
c.模擬其他事件
d.自定義DOM事件
方法:創建事件對象,初始化事件對象,觸發事件。
2.IE中的事件模擬