DOM2級事件繫結的相容處理
阿新 • • 發佈:2018-11-29
DOM2的相容處理
DOM2事件繫結,標準瀏覽器和IE低版本瀏覽器中除了語法上的區別,還有其它方面的區別
THIS問題
標準
執行事件池中繫結的方法,方法中的THIS是當前操作的元素;會給方法傳遞事件物件進來,事件物件中存在TARGET等屬性;IE低版本
執行方法的時候,方法中的THIS是WINDOW而不是當前元素;事件物件也傳遞進來了,但是傳遞進來的值和window.event一樣(和標準瀏覽器中的事件物件是有區別的)
重複問題
標準
如果我們繫結的方法重複了,瀏覽器不會把重複的方法新增到事件池中IE低版本
如果我們繫結的方法重複了,瀏覽器沒有內建識別重複的機制,導致事件中有重複的方法,執行的時候,一個方法可能會被執行多次
順序問題
標準
執行的順序是按照繫結的順序(事件池中方法排列的順序:標準瀏覽器中會把後面繫結的方法放在事件池的末尾)依次執行的IE低版本
繫結的方法過多的時候,不知道是由於向事件池中增加的時候順序混亂了,還是執行的時候順序混亂了,總之執行的順序和繫結的順序是沒關係的
我們DOM2事件相容處理,其實就是想把IE低版本瀏覽器中的機制,改變成為和標準瀏覽器一模一樣的機制(只需要處理IE低版本瀏覽器即可,高版本或者標準瀏覽器不去做任何特殊處理,按照瀏覽器預設的機制來執行即可)
IE低版本瀏覽器之所以出現這些問題,都是內建的事件池機制惹得禍,如果我們想讓他和標準的機制一樣,我們無法修改內建的東西,只能自己虛造出一個事件池,讓虛造的事件池和標準一樣,讓IE低版本瀏覽器走我們自己虛造的事件池
~function () {
/* Array.prototype.myBind=function myBind(context) {
var _this=this;
var outer=[].slice.call(arguments,1);
return function () {
/!* var inner=[].slice.call(arguments);*!/
_this.apply(context,outer)
}
};*/
function on(curEle, type, fn) {
//如果說是在標準瀏覽器下面的話,我們直接呼叫addEventListener這個方法即可,下面的程式碼也不用在執行了。
if ("addEventListener" in curEle) {
curEle.addEventListener(type, fn, false)
}
return;
//我們利用自定義屬性來建立一個事件池,讓每一個事件對應一個事件池,
if (!curEle[type + "poor"]) {
curEle[type + "poor"] = [];
//程式碼如果說能執行到這裡說明是在IE瀏覽器下面執行的,呼叫的是attachEvent進行監聽,我們在這裡呼叫run方法,需要改變this我們通過放在一個函式裡面在裡面通過call方法來改變this的指向,通過傳遞我們的事件物件window.event
curEle.attachEvent("on" + type, function () {
run.call(curEle, window.event)
})
}
/*
* curEle.attachEvent("on"+type,run.myBind(curEle))
* */
var ary = curEle[type + "poor"];
for (var i = 0; i < ary.length; i++) {
if (ary[i] === fn) return;
ary.push(fn)
}
}
function off(curEle, type, fn) {
if ("removeEventListener" in curEle) {
curEle.removeEventListener(type, fn, false)
}
return;
var ary = curEle[type + "poor"] || [];
for (var i = 0; i < ary.length; i++) {
if (ary[i] === fn) {
ary[i] = null;
break;
}
}
}
function run(e) {
if (!e.target) {
e.target = e.srcElement;
e.pageX = e.clientWidth + (document.documentElement.scrollTop || document.body.scrollTop);
e.pageY = e.clientHeight + (document.documentElement.scrollLeft || document.body.scrollLeft);
e.stopPropagation = function () {
e.cancelBubble = true;
}
e.preventDefault = function () {
e.stopPropagation = false;
}
}
var ary = this[e.type + "poor"];
if (ary) {
for (var i = 0; i < ary.length; i++) {
var item = ary[i];
if (!item) {
//我們在off的時候將其置為了null,!item=true
ary.splice(i, 1);
i--;
//i--是為了解決陣列塌陷的問題
continue;
}
ary[i].call(this, e)
//使用call方法來改變this,ie下面沒有事件引數,我們需要傳遞一個。
}
}
}
//將我們定義的方法暴露在全域性,方便自己以後呼叫
window.wgh = {
on: on,
off: off
}
}();
window.wgh.on(document.body, 'click', function () {
console.log('aaa')
});