js前端--解決非IE瀏覽器事件綁定的一些問題

來源:互聯網
上載者:User

標籤:

一.問題所在

現代綁定中W3C使用的是:addEventListener和removeEventListener。IE使用的是attachEvent和detachEvent。我們知道IE的這兩個問題多多,並且伴隨記憶體流失。所以,解決這些問題非常有必要。

那麼我們希望解決非IE瀏覽器事件綁定哪些問題呢?

1.支援同一元素的同一事件控制代碼可以綁定多個監聽函數;

2.如果在同一元素的同一事件控制代碼上多次註冊同一函數,那麼第一次註冊後的所有註冊都被忽略;

3.函數體內的this指向的應當是正在處理事件的節點(如當前正在運行事件控制代碼的節點);

4.監聽函數的執行順序應當是按照綁定的順序執行;

5.在函數體內不用使用 event = event || window.event; 來標準化Event對象;

 

二.設定代碼

//跨瀏覽器添加事件

function addEvent(obj, type, fn) {

if (typeof addEventListener != ‘undefined‘) {

obj.addEventListener(type, fn, false);

} else if (typeof attachEvent != ‘undefined‘) {

obj.attachEvent(‘on‘ + type, fn);

}

}

 

//跨瀏覽器刪除事件

function removeEvent(obj, type, fn) {

if (typeof removeEventListener != ‘undefined‘) {

obj.removeEventListener(type, fn);

} else if (typeof detachEvent != ‘undefined‘) {

obj.detachEvent(‘on‘ + type, fn);

}

}

 

上面的這兩個函數解決了:1.同時綁定多個函數;2.標準event;

上面的這兩個函數沒有解決的問題:1.IE多次註冊同一函數未被忽略;2.IE中順序是倒序;3.IE中this傳遞過來的是window

 

為瞭解決this傳遞問題,我們需要使用匿名函數+傳遞方式參數的方式來解決:

obj.attachEvent(‘on‘ + type, function () {

fn(obj);

});

 

addEvent(oButton, ‘click‘, function (_this) {

alert(_this.value);

});

 

這種方式比較古板,更好一點的方式是使用call來冒充對象。

obj.attachEvent(‘on‘ + type, function () {

fn.call(obj);

});

 

addEvent(oButton, ‘click‘, function () {

alert(this.value);

});

 

call的用法回憶一下:

fn.call(obj); //this就是obj對象

fn.call(123); //this就是123

fn.call(123,456); //this就是123,第一個參數是456

 

PS:也就是說,使用了call第一個參數就是this擷取,從第2個參數開始,可以通過函數參數擷取,以此類推。

 

使用了call傳遞this,帶來的諸多另外的問題:1.無法標準化event;2.無法刪除事件。導致的原因很明確,就是使用了匿名函數。標準化event可以解決,無法刪除事件就沒有辦法了,因為無法確定是哪一個事件。

obj.attachEvent(‘on‘ + type, function () {

fn.call(obj, window.event);

});

我們嘗試著通過使用傳統事件綁定對IE進行封裝。

 

//跨瀏覽器添加事件綁定

 

function addEvent(obj, type, fn) {

 

if (typeof obj.addEventListener != ‘undefined‘) {

 

obj.addEventListener(type, fn, false);

 

} else {

 

//建立一個可以儲存事件的雜湊表(散列表)

 

if (!obj.events) obj.events = {};

 

if (!obj.events[type]) {

 

//建立一個可以儲存事件處理函數的數組

 

obj.events[type] = [];

 

//儲存第一個事件處理函數

 

if (obj[‘on‘ + type]) obj.events[type][0] = fn;

 

}

 

//通過事件計數器來從第二個事件處理函數開始

 

obj.events[type][addEvent.ID++] = fn;

 

//執行所有事件處理函數

 

obj[‘on‘ + type] = function () {

 

for (var i in obj.events[type]) {

 

obj.events[type][i]();

 

}

 

}

 

}

 

}

 

//每個事件分配一個ID計數器

 

addEvent.ID = 1;

//跨瀏覽器添加事件綁定

function addEvent(obj, type, fn) {

if (typeof obj.addEventListener != ‘undefined‘) {

obj.addEventListener(type, fn, false);

} else {

//建立事件類型的散列表(雜湊表)

if (!obj.events) obj.events = {};

//建立存放事件處理函數的數組

if (!obj.events[type]) {

obj.events[type] = [];

//儲存第一個事件處理函數

if (obj[‘on‘ + type]) {

obj.events[type][0] = fn;

}

//執行事件處理

obj[‘on‘ + type] = addEvent.exec;

} else {

//同一個註冊函數取消計數

if (addEvent.array(fn,obj.events[type])) return false;

}

//從第二個開始,通過計數器儲存

obj.events[type][addEvent.ID++] = fn;

}

}

 

addEvent.array = function (fn, es){

for (var i in es) {

if (es[i] == fn) return true;

}

return false;

}

 

//每個事件處理函數的ID計數器

addEvent.ID = 1;

 

//事件處理函數調用

addEvent.exec = function (event) {

var e = event || addEvent.fixEvent(window.event);

var es = this.events[e.type];

for (var i in es) {

es[i].call(this, e);

}

};

 

//擷取IE的event,相容W3C的調用

addEvent.fixEvent = function (event) {

event.preventDefault = addEvent.fixEvent.preventDefault;

event.stopPropagation = addEvent.fixEvent.stopPropagation;

return event;

};

 

//相容IE和W3C阻止預設行為

addEvent.fixEvent.preventDefault = function () {

this.returnValue = false;

};

 

//相容IE和W3C取消冒泡

addEvent.fixEvent.stopPropagation = function () {

this.cancelBubble = true;

};

 

//跨瀏覽器刪除事件

function removeEvent(obj, type, fn) {

if (typeof obj.removeEventListener != ‘undefined‘) {

obj.removeEventListener(type, fn, false);

} else {

var es = obj.events[type];

for (var i in es) {

if (es[i] == fn) {

delete obj.events[type][i];

}

}

}

}

 

js前端--解決非IE瀏覽器事件綁定的一些問題

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.