1.事件委託的原理以及優缺點 2. 手寫原生js實現事件代理,並要求相容瀏覽器
阿新 • • 發佈:2019-01-29
Q:事件的委託(代理 Delegated Events)的原理以及優缺點
A:委託(代理)事件是那些被繫結到父級元素的事件,但是隻有當滿足一定匹配條件時才會被挪。這是靠事件的冒泡機制來實現的,
優點是:
(1)可以大量節省記憶體佔用,減少事件註冊,比如在table上代理所有td的click事件就非常棒
(2)可以實現當新增子物件時無需再次對其繫結事件,對於動態內容部分尤為合適
缺點是:
事件代理的應用常用應該僅限於上述需求下,如果把所有事件都用代理就可能會出現事件誤判,即本不應用觸發事件的被綁上了事件。
例子:
Pencil Pen Eraser
|
var toolbar = document.querySelector( ".toolbar" );
toolbar.addEventListener( "click" , function (e) {
var button = e.target;
if (!button.classList.contains( "active" ))
button.classList.add( "active" );
else
button.classList.remove( "active" );
});
|
單擊button元素會冒泡到UL.toolbar元素,使用了e.target來定位到當前點選的button。
Q:手寫原生js實現事件代理,並要求相容瀏覽器
A:其實就是考核對事件物件e的瞭解程度,以及在IE下對應的屬性名。
// ============ 簡單的事件委託
function delegateEvent(interfaceEle, selector, type, fn) {
if (interfaceEle.addEventListener){
interfaceEle.addEventListener(type, eventfn);
} else {
interfaceEle.attachEvent( "on" +type, eventfn);
}
function eventfn(e){
var e = e || window.event;
var target = e.target || e.srcElement;
//如果目標元素與選擇器匹配則執行函式
if (matchSelector(target, selector)) {
if (fn) {
//將fn內部的this指向target(在此之前this都是指向的繫結事件的元素即interfaceEle)
fn.call(target, e);
}
}
}
}
/**
* only support #id, tagName, .className
* and it's simple single, no combination
*/
//比較函式:判斷事件的作用目標是否與選擇器匹配;匹配則返回true
function matchSelector(ele, selector) {
//
如果選擇器為ID
if (selector.charAt(0) === "#" ) {
return ele.id === selector.slice(1);
}
//charAt(0),返回索引為0的字元
//slice(a,b),從已有的陣列或字串返回從索引從a處開始,擷取到索引b之前的子陣列或子字串;
//如果選擇器為Class
if (selector.charAt(0) === "." ) {
return ( " " + ele.className + " " ).indexOf( " " + selector.slice(1) + " " ) != -1;
}
//
如果選擇器為tagName
return ele.tagName.toLowerCase() === selector.toLowerCase();
}
//toLowerCase()將字串轉換成小寫
//呼叫
var odiv = document.getElementById( "oDiv" );
delegateEvent(odiv, "a" , "click" , function (){
alert( "1" );
})
|