1. 程式人生 > >DOM2級事件繫結的相容處理

DOM2級事件繫結的相容處理

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') });