主要內容:
addEventListener綁定方式的問題:
document.body.addEventListener( 'click',
function() {
alert('body clicked');
},false);
以及第二個參數為object的優勢:
document.body.addEventListener('click',
{
handleEvent: function() {
alert('body clicked');
}
},
false);
原文廢話太多,我隻翻譯瞭主要部分。
具體細節,請自行查看
正文
先簡短的看一下各個瀏覽器提供的DOM元素事件綁定接口:
//IE使用element.attachEvent:
document.body.attachEvent(
'onclick',
function() {
alert('body clicked');
});
//其他瀏覽器使用element.addEventListener:
document.body.addEventListener(
'click',
function() {
alert('body clicked');
},
false);
一般來說上面的第二個參數都是傳入一個函數句柄,但是大多數javascript程序員並不知道第二個參數可以傳入一對象obj【DOM2接口http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-EventListener】,如此一來,當event執行的時候,會隱式的調用obj的handleEvent方法。
document.body.addEventListener(
'click',
{
handleEvent: function() {
alert('body clicked');
}
},
false);
這麼做的一個重要方面是obj的handleEvent隻有在執行的時候才需要去訪問【有點類似延遲綁定的效果】。同時,如果在兩次event事件間隔中,handleEvent發生瞭改變,那麼產生的效果會跟著改變。這樣一個好處就是不用remove事件而直接切換事件。
看下面的例子:
document.body.addEventListener('click', obj, false);
// click body will error in some browsers because
// 現在還沒有事件
obj.handleEvent = function() {alert('alpha');};
// 單擊彈出alpha
obj.handleEvent = function() {alert('beta');};
// 單擊彈出"beta"
document.body.removeEventListener('click', obj, false);
//單擊什麼都沒有瞭
【註意,這個用法存在一定的兼容性問題。不過我現在隻面向手機瀏覽器,所以請自行測試】
跨瀏覽器的事件綁定
對於事件綁定,各種庫都會處理兼容問題,統一API,大都類似:
LIB_addEventListener(
document.body,
'click',
function() {
alert('body clicked');
});
個人實現的一個:
//一個封裝
function LIB_addEventListener(el,type,fn){
el.addEventListener(type,fn,false);
}
function ViewObject() {
this.data = 'alpha';
LIB_addEventListener(document.body,'click',this.handleClick);
}
ViewObject.prototype.handleClick = function() {
console.log(this.data);
};
var test = new ViewObject();//單擊彈出undefined
我們期望彈出‘alpha’,但是this指向window,彈出的是undefined;
解決方式,有的庫添加瞭第四個參數,用來制定上下文:
function LIB_addEventListener(el,type,fn,obj){
el.addEventListener(type,fn.bind(obj),false);
}
function ViewObject() {
this.data = 'alpha';
LIB_addEventListener(document.body,'click',this.handleClick,this);
}
ViewObject.prototype.handleClick = function() {
console.log(this.data);
};
var test = new ViewObject();
此時我們彈出來‘alpha’
這種方式的問題:listener在綁定的時候就已經固定瞭,於是問題就又來瞭。
function LIB_addEventListener(el,type,fn,obj){
el.addEventListener(type,fn.bind(obj),false);
}
function ViewObject() {
this.data = 'alpha';
LIB_addEventListener(document.body,'click',this.handleClick,this);
}
ViewObject.prototype.handleClick = function() {
console.log(this.data);
};
var test = new ViewObject();
test.handleClick = function(){
console.log('new fn');//單擊彈出的依舊是alpha。我們希望的是new fn
}
采用obj的綁定形式:
function LIB_addEventListener(el,type,obj){
el.addEventListener(type,obj,false);
}
function ViewObject() {
this.data = 'alpha';
LIB_addEventListener(document.body, 'click', this);
LIB_addEventListener(document.body, 'mousemove', this);
}
ViewObject.prototype.handleEvent = function(e) {
if('click' == e.type){
console.log(this.data)
}else{
console.log('not click')
}
};
var test = new ViewObject();
上面的例子我改瞭一下,但是可以說明問題。這樣的靈活性也高一些。
摘自 西山