《Javascript 高階程式設計(第三版)》筆記0x19 事件:記憶體和效能、模擬事件
目錄
記憶體和效能
事件委託
對“事件處理程式過多”問題的解決方案就是事件委託。事件委託利用了事件冒泡,只指定一個事件處理程式,就可以管理某一型別的所有事件。例如, click 事件會一直冒泡到 document 層次。也就是說,我們可以為整個頁面指定一個 onclick 事件處理程式,而不必給每個可單擊的元素分別新增事件處理程式。
<ul id="myLinks"> <li id="goSomewhere">Go somewhere</li> <li id="doSomething">Do something</li> <li id="sayHi">Say hi</li> </ul>
var list = document.getElementById("myLinks"); EventUtil.addHandler(list, "click", function(event){ event = EventUtil.getEvent(event); var target = EventUtil.getTarget(event); switch(target.id){ case "doSomething": document.title = "I changed the document's title"; break; case "goSomewhere": location.href = "http://www.wrox.com"; break; case "sayHi": alert("hi"); break; } });
移除事件處理程式
記憶體中留有那些過時不用的“空事件處理程式”(dangling event handler),也是造成 Web 應用程式記憶體與效能問題的主要原因。
//從文件中移除帶有事件處理程式的元素時
<div id="myDiv">
<input type="button" value="Click Me" id="myBtn">
</div>
<script type="text/javascript">
var btn = document.getElementById("myBtn");
btn.onclick = function(){
//先執行某些操作
btn.onclick = null; //移除事件處理程式
document.getElementById("myDiv").innerHTML = "Processing...";
};
</script>
模擬事件
DOM中的事件模擬
模擬滑鼠事件
建立新的滑鼠事件物件併為其指定必要的資訊,就可以模擬滑鼠事件。建立滑鼠事件物件的方法是為 createEvent()傳入字串"MouseEvents"。返回的物件有一個名為 initMouseEvent()方法,用於指定與該滑鼠事件有關的資訊。
var btn = document.getElementById("myBtn");
//建立事件物件
var event = document.createEvent("MouseEvents");
//初始化事件物件
//接收 15 個引數,分別與滑鼠事件中每個典型的屬性一一對應
event.initMouseEvent("click", true, true, document.defaultView, 0, 0, 0, 0, 0,
false, false, false, false, 0, null);
//觸發事件
btn.dispatchEvent(event);
模擬鍵盤事件
DOM3 級規定,呼叫 createEvent()並傳入"KeyboardEvent"就可以建立一個鍵盤事件。返回的事件物件會包含一個 initKeyEvent()方法,這個方法接收下列引數。
type(字串):表示要觸發的事件型別,如"keydown"。
bubbles(布林值):表示事件是否應該冒泡。為精確模擬滑鼠事件,應該設定為 true。
cancelable(布林值):表示事件是否可以取消。為精確模擬滑鼠事件,應該設定為 true。
view (AbstractView ):與事件關聯的檢視。這個引數幾乎總是要設定為 document.defaultView。
key(布林值):表示按下的鍵的鍵碼。
location(整數):表示按下了哪裡的鍵。 0 表示預設的主鍵盤, 1 表示左, 2 表示右, 3 表示數字鍵盤, 4 表示移動裝置(即虛擬鍵盤), 5 表示手柄。
modifiers(字串):空格分隔的修改鍵列表,如"Shift"。
repeat(整數):在一行中按了這個鍵多少次。
//按 住 Shift 的 同 時 又 按 下 A 鍵
var textbox = document.getElementById("myTextbox"),event;
//以 DOM3 級方式建立事件物件
if (document.implementation.hasFeature("KeyboardEvents", "3.0")){
event = document.createEvent("KeyboardEvent");
//初始化事件物件
event.initKeyboardEvent("keydown", true, true, document.defaultView, "a",
0, "Shift", 0);
}
//觸發事件
textbox.dispatchEvent(event);
模擬其他事件
模擬變動事件,可以使用createEvent("MutationEvents") 建立一個含initMutationEvent() 方法的變動事件物件 。這個方法接受的引數包括 :type 、bubbles 、cancelable、relatedNode、preValue、newValue、attrName 和 attrChange。
var event = document.createEvent("MutationEvents");
event.initMutationEvent("DOMNodeInserted", true, false, someNode, "","","",0);
target.dispatchEvent(event);
模擬HTML事件,需要先建立一個 event 物件——通過createEvent("HTMLEvents"),然後再使用這個物件的initEvent()方法來初始化它即可
var event = document.createEvent("HTMLEvents");
event.initEvent("focus", true, false);
target.dispatchEvent(event);
自定義 DOM 事件
自定義事件不是由 DOM 原生觸發的,它的目的是讓開發人員建立自己的事件。要建立新的自定義事件,可以呼叫 createEvent("CustomEvent")。返回的物件有一個名為 initCustomEvent()的方法,接收如下 4 個引數
type(字串):觸發的事件型別,例如"keydown"。
bubbles(布林值):表示事件是否應該冒泡。
cancelable(布林值):表示事件是否可以取消。
detail(物件):任意值,儲存在 event 物件的 detail 屬性中。
var div = document.getElementById("myDiv"),event;
EventUtil.addHandler(div, "myevent", function(event){
alert("DIV: " + event.detail);
});
EventUtil.addHandler(document, "myevent", function(event){
alert("DOCUMENT: " + event.detail);
});
if (document.implementation.hasFeature("CustomEvents", "3.0")){
event = document.createEvent("CustomEvent");
event.initCustomEvent("myevent", true, false, "Hello world!");
div.dispatchEvent(event);
}
IE中的事件模擬
//模擬了在一個按鈕上觸發 click 事件過程
var btn = document.getElementById("myBtn");
//建立事件物件
var event = document.createEventObject();
//初始化事件物件
event.screenX = 100;
event.screenY = 0;
event.clientX = 0;
event.clientY = 0;
event.ctrlKey = false;
event.altKey = false;
event.shiftKey = false;
event.button = 0;
//觸發事件
btn.fireEvent("onclick", event);