所謂事件,就是文檔或閱讀器窗口中產生的1些特定的交互瞬間
在頁面上,單擊某個元素的同時,也單擊了它的包括容器。事件流就是描寫的從頁面中接收事件的順序。IE是事件冒泡流,Netscape是事件捕獲流。
事件冒泡:事件開始時,由最具體的元素接收,然后逐級向上傳播到較為不具體的節點;(所有現代閱讀器都支持事件冒泡)
事件捕獲:不太具體的節點最早接收到事件,最具體的節點最后接收到事件。(老版本閱讀器不支持)
DOM2級事件規定的事件流包括3個階段:1、事件不惑階段;2、處于目標階段;3、事件冒泡階段
DOM事件流中,實際的目標在捕獲階段不會接收到時間
事件就是用戶或閱讀器本身履行的某種動作,如click/load/mousedown,這些都是事件的名字。
事件處理程序:是響應某個事件的函數
為事件指定事件處理函數的方法有3種:
某個元素支持的每種事件,都可以在元素內部,使用與事件處理程序同名的HTML屬性來指定。這個屬性的值是能夠履行的JavaScript代碼,既可以包括要履行的具體動作,也能夠調用在頁面其他地方定義的腳本。
<input type="button" value="點我有欣喜" onclick="alert('hello,vicky!')" />
缺點:
1、存在時差,用戶可能會在HTML元素加載完就觸發相應事件,而這時候相應的事件處理程序還沒有加載完,就會報錯
2、使得HTML代碼和JavaScript代碼耦合,所以不推薦使用!
每一個元素都有自己的事件處理程序屬性,這些屬性通常全部小寫,將這類屬性的值設置為1個函數,就能夠指定事件處理程序。
var btn = document.getElementById("btn");//獲得1個要操作對象的援用
btn.onclick = function () {
alert("hello vicky!");
}
DOM2級事件定義了兩個方法:addEventListener( ) removeEventListener( ),都接受3個參數,要處理的事件名,事件處理函數,1個布爾值(true表示在捕獲階段調用事件處理程序,false表示在冒泡階段)
var btn = document.getElementById("btn");
btn.addEventListener("click", function (){
alert("hello vicky!");
},false);
btn.addEventListener("click",function () {
alert("hello jay!")
}, false);//可以添加多個事件處理程序,且依照其添加的順序觸發
通過addEventListener()添加的事件處理程序只能通過 removeEventListener()來移出。事件處理程序是在其依附的元素的作用域中運行
IE實現了與DOM中類似的兩個方法:attachEvent()和detachEvent()。事件處理程序在全局作用域中運行,添加的事件處理程序都會被添加到冒泡階段
var btn = document.getElementById("btn");
btn.attachEvent("onclick",function(){
alert("hello vicky!");
});
btn.attachEvent("onclick",function () {
alert("hello jay!");
});//添加多個事件處理程序,以添加順序的相反順序履行
var EventUtil = {
//添加事件處理程序
addHandler: function (element,type,handler) {
if (element.addEventListener) {
element.addEventListener(type,handler,false);//DOM2級
} else if (element.attachEvent) {
element.attachEvent("on" + tye,handler);//IE的方法
} else {
element["on" + tyle] = handler;//DOM0級
}
},
//取消事件處理程序
removeHandler: function (element,type,handler) {
if (element.removeEventListener) {
element.removeEventListener(type,handler,false);
} else if (element.detachEvent) {
element.detachEvent("on" + tye,handler);
} else {
element["on" + tyle] = null;
}
}
}
在動身DOM上的某個事件時,會產生要給事件對象event
兼容DOM的閱讀器會將1個event對象傳入到事件處理程序中。event對象包括于創建它的特定事件有關的屬性和方法。
//屬性
bubbles:Boolean //表明事件是不是冒泡
cancelable:Boolean //表明是不是可以取消事件的默許行動
currentTarget:Element //事件處理程序當前正在處理事件的那個元素
defaultPrevented:Boolean //是不是調用了preventDefault()
detail:Integer //細節信息
eventPhase: Integer //1,捕獲階段;2,處于目標階段;3,冒泡階段
target:Element //事件的目標
trusted:Boolean //是不是為閱讀器生成
type:Sting //被觸發事件的類型
//方法
preventDefault() //取消事件的默許行動
stopImmediatePropagation() //取消事件的進1步捕獲或冒泡,同時禁止任何事件處理程序被調用
stopPropagation() //取消事件的進1步捕獲或冒泡。
在事件處理程序內部,對象this始終等于currentTarget的值,target則只包括事件的實際目標
不同的地方:
1、event對象作為window對象的1個屬性存在
2、事件的目標 window.event.srcElement
3、returnValue=false相當于preventDefault()
var EventUtil = {
//獲得事件對象
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.cancleBubble = true;
}
}
}
UI事件:指的是那些不1定與用戶操作有關的事件。主要有:
load事件:頁面完全加載后再window上面觸發
unload事件:頁面完全卸載后在window上觸發
abort事件:用戶停止下載進程時,如果嵌入的內容還沒加載完在object元素上面觸發
error事件:產生毛病時觸發
select事件:用戶選擇文本框時觸發
resize事件:窗口或框架的大小變化時觸發
scroll事件:用戶轉動帶轉動條的元素中的內容時觸發
當頁面完全加載后,就會觸發window上面的load事件
注意:在創建新的img元素時,要在指定其src屬性之前先指定事件。新圖象元素不1定要從添加到文檔后才開始下載,只要設置了src屬性就會開始下載。
注意:與圖象不同,只有在設置了script元素的src屬性并將該元素添加到文檔后,才會開始下載JavaScript文件,即指定src屬性和指定事件處理程序的前后順序不重要。
在文檔被完全卸載后觸發,只要用戶從1個頁面切換到另外一個頁面,就會產生unload事件。
當閱讀器窗口被調劑到1個新的高度或寬度時,就會觸發resize事件
注意:不要在這個事件的處理程序中加入計算量大的代碼,由于這些代碼很有可能會被頻繁履行,從而致使閱讀器反應明顯變慢。固然,這個缺點也是有辦法來解決的,那就是函數節流 ,詳情請見之前博客【JavaScript】函數節流
blur:在元素失去焦點時觸發
focus:在元素取得焦點時觸發
這兩個事件都不冒泡,所有閱讀器都支持它們
click:單擊主鼠標或按下回車鍵觸發
dbclick:雙擊主鼠標時觸發
mousedown:用戶按下了任意鼠標按鈕時觸發
mouseenter:在鼠標光標從元素外部首次移動到元素范圍以內時觸發。此事件不冒泡,且光標移動到后代元素上不觸發
mouseleave:位于元素上的光標移動到元素范圍以外時觸發
mouseover:鼠標指針在元素內部移動時觸發
mouseout:鼠標指針由1個元素移到另外一個元素上時觸發
mouseup:釋放鼠標按鈕時觸發
//鼠標事件觸發順序
(1)mousedown
(2)mouseup
(3)click
(4)mousedown
(5)mouseup
(6)dbclick
1)位置屬性:
clientX,clientY:到閱讀器視口區的左側和上邊的值
screenX,screenY:到顯示屏幕左側和上邊的值
offsetX,offsetY:到元素左側和上邊的值
2)修改鍵
shiftKey,ctrlKey,altKey,metaKey.
//打印出用戶按下的修改鍵
var text = document.getElementById("text");
EventUtil.addHandler(text,"keydown",function (event) {
var event = EventUtil.getEvent(event);
var keys = new Array();
if (event.shiftKey) {
keys.push("shift")
}
if (event.ctrlKey) {
keys.push("ctrl");
}
console.log(keys);
}) ;
3)相干元素
產生mouseover和mouseout事件時,還會觸及更多的元素。這兩個事件都會觸及把鼠標指針從1個元素的編輯以內移動到另外一個元素的邊界以內
//獲得相干元素
getRelatedTarget: function (event) {
if (event.relatedTarget) {//DOM
return event.relatedTarget;
} else if (event.toElement) {//mouseout時IE的toElement保存相干元素
return event.toElement;
} else if (event.fromElement) {//mouseover時IE的fromElement保存相干元素
return event.fromElement;
} else {
return null;
}
}
4)鼠標按鈕
event對象存在1個button屬性,其值有3種:0表示主鼠標按鈕,1表示中間的鼠標按鈕,2表示次鼠標按鈕
將mousewheel事件處理程序指定給頁面中的任何元素或document對象,便可處理鼠標滾輪交互操作
使用鼠標事件應注意的問題:
(1)使用click事件履行代碼
(2)不要使用onmouseover向用戶顯示新的選項。緣由是 屏幕瀏覽器中,沒法觸發mousedown和mouseover事件
(3)不要使用dbclick履行重要的操作。由于鍵盤沒法觸發這個事件
keydown:用戶按下鍵盤上的任意鍵時觸發
keypress:用戶按下鍵盤上的字符鍵時觸發
keyup:用戶釋放鍵盤上的鍵時觸發
textInput:在文本插入文本框之前觸發
在產生keydown和keyup事件時,event對象的keyCode屬性中會包括1個代碼,與鍵盤上1個特定的鍵對應。
產生keypress事件意味著按下的鍵會影響到屏幕中文本的顯示。
charCode屬性:只有在產生keypress事件時才包括值,而且值是ASCII編碼。要想跨閱讀器獲得字符編碼,必須首先檢測charCode屬性是不是可用,如果不可用則使用keyCode
//獲得charCode
getCharCode: function (event) {
if (typeof event.charCode == "number") {
return event.charCode;
} else {
return event.keyCode;
}
}
用戶在可編輯區域中輸入字符時,就會觸發這個事件
textInput事件的event對象中包括1個data屬性,這個屬性的值就是用戶輸入的字符(不是編碼)。
var textbox = document.getElementById("textbox");
EventUtil.addHandler(textbox,"textInput",function (event) {
event = EventUtil.getEvent(event);
alert(event.data);
})
contextmenu事件表示什么時候應當顯示上下文菜單,以便開發人員取消默許的上下文菜單而提供自定義的菜單
//contextmenu事件
EventUtil.addHandler(window,"load",function (event) {
var div = document.getElementById("myDiv");
EventUtil.addHandler(div, "contextmenu", function (event) {
event = EventUtil.getEvent(event);
EventUtil.preventDefault(event);
var menu = div.nextElementSibling;
menu.style.left = event.clientX + "px";
menu.style.right = event.clientY + "px";
menu.style.visibility = "visible";
});
EventUtil.addHandler(document, "click", function (event) {
document.getElementById("myMenu").style.visibility = "hidden";
})
});
右鍵出現自定義的上下文信息
readystatechange事件的目的是提供與文檔或元素的加載狀態有關的信息
可能的狀態有5種:
uninitialized(未初始化):對象存在但還沒有初始化
loading(正在加載):對象正在加載數據
loaded(加載終了):對象加載數據完成
interactive(交互):可以操作對象了,但還沒有完全加載
complete(完成):對象已加載終了
并不是所有對象都會經歷readyState的這幾個階段
栗子:
//readystatechange事件,肯定外部js是不是加載終了
EventUtil.addHandler(window, "load", function () {
var script = document.createElement("script");
EventUtil.addHandler(script, "readystatechange", function (event) {
var event = EventUtil.getEvent(event);
var target = event.getTarget(event);
if (target.readyState == "loaded" || target.readyState == "complete") {
EventUtil.removeHandler(target, "readystatechange", arguments.callee);
alert("event.js is loaded");
}
});
script.src = "test.js";
document.body.appendChild(script);
});
//readystatechange 事件,肯定外部css是不是加載終了
EventUtil.addHandler(window, "load", function () {
var link = document.createElement("link");
link.type = "text/css";
link.rel = "stylesheet";
EventUtil.addHandler(link,"readystatechange", function (event) {
var event = EventUtil.getEvent(event);
var target = EventUtil.getTarget(event);
if (target.readyState == "loaded" || target.readyState == "complete") {
EventUtil.removeHandler(target, "readystatechange", arguments.callee);
}
});
link.href = "test.css";
document.getElementsByTagName("head")[0].appendChild(link);
});
//以上兩個函數,最重要的是1并檢測readyState的兩個狀態,并在調用了1次事件處理程序后就將其移除
對”事件處理程序過量“這個問題的解決方案就是事件拜托,事件拜托利用了事件冒泡,只指定1個事件處理程序,就能夠管理某1類型的所有事件。比如,click事件會冒泡到document對象上,所以可以為全部頁面指定1個onclick事件處理程序,而沒必要給每一個可單擊的元素分別添加。
事件拜托的優點:
(1)在頁面中設置時間處理程序所需的時間更少。只添加1個事件處理程序所需的DOM援用更少,花費時間少
(2)全部頁面占用的內存空間更少,能夠提升整體性能。
合適使用時間拜托技術的事件有:click/mousedown/mouseup/keydown/keyup/keypress
內存中留有那些過時不用的“空事件處理程序”,也是造成Web利用程序內存與性能問題的主要緣由,解決問題的1種方法就是移除這些事件處理程序。
btn.onclick = null;
在頁面卸載之前,使用onunload事件,移除所有事件處理程序
String.fromCharCode( ): 可接受1個指定的Unicode值,返回對應的字符串
/\d/.test(String.fromCharCode(EventUtil.getCharCode(event)))//判斷按鍵按下的是不是為數字
hasArrtibute( ):如果存在指定屬性,則hasAttribute方法返回true,否則返回false。
specified屬性:HTML DOM屬性,查明是不是已規定某屬性
PS.《JavaScript高級程序設計》書又刷了1遍,還是又學習了很多新的知識,我覺著寫博客是1種鞏固學習的好方法,看書看1遍,把書上的代碼敲1遍,再在博客中梳理1遍,全部知識框架就會很清晰。最近心里也有點著急,看書速度有些慢了,又買了好幾本新書,不知道內推之前還來不來的及看完了。英雄不打無準備之仗,所以,加油!