JavaScript移除綁定在元素上的匿名事件處理函數


前言:

面試的時候有點蒙,結束之后想想自己好像根本就誤解了面試官的問題,因為我理解的這個問題本身就沒有意義。但是當時已經有一些思路,但是在一個點上被卡住。

結束之后腦子瞬間靈光,想出了當時沒有邁出的那一小步。所以不想計較這個問題本身的意義,單純的想要把這個我理解錯了的問題解決,就當是滿足自己一個小小的願望吧。

 

問題:

用addEventListener()和attachEvent()給一個DOM元素綁定事件處理程序時,如果傳入一個匿名函數,那么用相應的removeEventListener()和detachEvent()是無法將這個匿名的處理程序解除綁定的。所以我們用的時候應該傳入一個函數表達式。

那么,如果我就是想使用匿名函數進行綁定和解綁,怎么解決?

 

思路:

既然這兩個函數都高冷的說明了不接受相同的匿名函數進行解綁,那么就只能另尋出路,不能靠它來管理事件了。

所以需要一個自定義的對象來管理事件。

事件處理程序的本質就是,當一個事件在一個對象上發生時,執行監聽這個事件的函數。

翻譯一下:

一個DOM元素可能被綁定多個事件類型的處理程序。比如click的時候顏色改變,mouseover的時候變大。

一個事件類型可能綁定多個事件處理程序。比如mouseover的時候又變色又變大。

所以,這個事件對象應該有一個屬性用來存儲這個DOM元素上綁定的所有事件處理程序,還應該有兩個方法,一個用來添加,一個用來刪除。

{
handlers:{
type1:[handler1,handler2],
type2:[handler1,handler2],
...//其他事件類型和對應的事件處理函數
},
on:function(){},
off:function(){}
}

當一個事件發生時,就調用這個對象里面對應的事件類型的數組里面的所有函數。

所以綁定事件就是往對應的數組里面添加函數,解除綁定事件就是把這個函數從這個數組里面刪掉。

那么怎么保證操作的是那個正確的DOM元素呢?

顯然,每個DOM元素都應該需要一個這樣的對象,用於管理自己的事件處理程序。

每個對象都有的東西,那不就是他的屬性嘛。(而我當時就被卡在了這里)。

實現:

每個DOM元素都需要這樣一個對象,而且每個對象中的on()和off()方法都是相同的,所以需要一個構造函數,把這兩個方法放到他的原型對象中去。

function EventManage(){
  this.handlers={}
}
EventManage.prototype={
  on:function(type,handler){
    if(!this.handlers[type]){
      this.handlers[type]=[handler];
      return true;  //避免添加多個事件
    }else{
      this.handlers[type].push(handler);
    }
  },
  off:function(type,handler){
    for(var i=0,len=this.handlers[type].length;i<len;i++){
      if(this.handlers[type][i].toString()==handler.toString()){
        this.handlers[type].splice(i,1);
      }
    }
  }
}

每個對象有了這兩個方法,就可以自行添加和移除事件處理程序了,但是,監聽事件,還是要靠JavaScript提供的方法,所以借用addEventListner()和attachEvent()來監聽事件:

var EventUtil={};
EventUtil.on=function(ele,type,handler){
  if (!ele.event) {
    ele.event=new EventManage();
  }
  var isNewType=ele.event.on(type,handler);
  var fire=function(){
      for(var i=0,len=ele.event.handlers[type].length;i<len;i++){
        ele.event.handlers[type][i]();
      }
    };
  if (isNewType) {
    if (ele.addEventListener) {
      ele.addEventListener(type,fire,false);
    }else{
      ele.attachEvent("on"+type,fire);
    }
  }
}
EventUtil.off=function(ele,type,handler){
  ele.event.off(type,handler);
}

這里要注意一個問題,每次使用EventUtil.on()時都會重新定義一個fire函數,addEventListener()就會給相同的事件類型添加多個相同的事件處理程序,所以需要判斷一下這個事件類型是不是新增的,如果是的話再用addEventListener()來監聽這個事件類型。

 

使用示例:

var btn=document.getElementById("btn");

EventUtil.on(btn,"click",function(){
  console.log("11");
});
EventUtil.on(btn,"click",function(){
  console.log("22");
});
EventUtil.off(btn,"click",function(){
  console.log("11");
});

當點擊btn時,只打印了"22",說明匿名函數成功解綁。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM