js中事件綁定研究


本質:不同的庫或者工具中總是封裝了不同的事件綁定形式,但是究其根源,還是IE事件模型和W3C事件模型不同的處理方式

1)W3C事件模型:支持事件捕捉和冒泡 addEventListener('type',function(){},bool) removeEventListener ('type',function(){},bool)

2)IE事件模型:僅支持事件冒泡 attachEvent('type',function(){}); detachEvent('type',fucntion(){});

*如何統一:設置W3C事件綁定函數的第三個參數為false,那么就不支持事件捕捉了。 

*原生的綁定形式:

obj.addEventListener('type',function(){},false);

obj.attachEvent('type',function(){});

*是否有注意的:

當然有,IE對同一個事件綁定2次會重復綁定2次,但是W3C只會綁定一次,會忽略后面的一個事件。這個要特別注意,特別是在開發的時候

我記得我在使用百度tangram的處理問題的時候,還碰到了,后面我們來分析tangram的事件綁定形式。

*是否有解決方案:

當然有,對對象綁定以class的形式就可以解決。不會重復綁定事件了。實現方式也是多種多樣。

現在來看看一些框架中的事件綁定處理:

1)tangram:

 
baidu.event.on = function (element, type, listener) {
    type = type.replace(/^on/i, '');
    element = baidu.dom._g(element);
    var realListener = function (ev) {
            // 1. 這里不支持EventArgument,  原因是跨frame的事件掛載
            // 2. element是為了修正this
            listener.call(element, ev);
        },
        lis = baidu.event._listeners,
        filter = baidu.event._eventFilter,
        afterFilter,
        realType = type;
    type = type.toLowerCase();
    // filter過濾
    if(filter && filter[type]){
        afterFilter = filter[type](element, type, realListener);
        realType = afterFilter.type;
        realListener = afterFilter.listener;
    }
    
    // 事件監聽器掛載
    if (element.addEventListener) {
        element.addEventListener(realType, realListener, false);
    } else if (element.attachEvent) {
        element.attachEvent('on' + realType, realListener);
    }
  
    // 將監聽器存儲到數組中
    lis[lis.length] = [element, type, listener, realListener, realType];
    return element;
};
baidu.event.un = function (element, type, listener) {
    element = baidu.dom._g(element);
    type = type.replace(/^on/i, '').toLowerCase();
    
    var lis = baidu.event._listeners, 
        len = lis.length,
        isRemoveAll = !listener,
        item,
        realType, realListener;
    
    //如果將listener的結構改成json
    //可以節省掉這個循環,優化性能
    //但是由於un的使用頻率並不高,同時在listener不多的時候
    //遍歷數組的性能消耗不會對代碼產生影響
    //暫不考慮此優化
    while (len--) {
        item = lis[len];
        
        // listener存在時,移除element的所有以listener監聽的type類型事件
        // listener不存在時,移除element的所有type類型事件
        if (item[1] === type
            && item[0] === element
            && (isRemoveAll || item[2] === listener)) {
            realType = item[4];
            realListener = item[3];
            if (element.removeEventListener) {
                element.removeEventListener(realType, realListener, false);
            } else if (element.detachEvent) {
                element.detachEvent('on' + realType, realListener);
            }
            lis.splice(len, 1);
        }
    }
    
    return element;

}; 

可以看出tangram不過是變了一個綁定的方式,其本質還是一樣的。

2)jquery

// Only use addEventListener/attachEvent if the special events handler returns false
  if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
// Bind the global event handler to the element
  if ( elem.addEventListener ) {
  elem.addEventListener( type, eventHandle, false );
  } else if ( elem.attachEvent ) {
elem.attachEvent( "on" + type, eventHandle );
  }

  } 

可以看出也是對是否支持 addEventListener和attachEvent  按后進行綁定處理的。

3) prototype

 function observe(element, eventName, handler) {

    element = $(element);
    var responder = _createResponder(element, eventName, handler);
    if (!responder) return element;
    if (eventName.include(':')) {
      if (element.addEventListener)
        element.addEventListener("dataavailable", responder, false);
      else {
        element.attachEvent("ondataavailable", responder);
        element.attachEvent("onlosecapture", responder);
      }
    } else {
      var actualEventName = _getDOMEventName(eventName);
      if (element.addEventListener)
        element.addEventListener(actualEventName, responder, false);
      else
        element.attachEvent("on" + actualEventName, responder);
    }
    return element;
  }

可以看出也是對IE和W3C支持的事件模型進行處理的。不過是處理的函數,方式不同而已。

 

 


免責聲明!

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



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