如何在事件代理中正确使用 focus 和 blur 事件

什么是事件代理(Event Delegation)?

如果不太了解的朋友,可详细阅读:《Event delegation in JavaScript》,这里不再累述。

首先让我们一起来回顾一些常识:

  1. 通常支持事件冒泡(Event Bubbling)的事件类型为鼠标事件和键盘事件,例如:mouseover, mouseout, click, keydown, keypress
  2. 接口事件则通常不支持事件冒泡(Event Bubbling),例如:load, change, submit, focus, blur

很明显:focus 和 blur 都属于不支持冒泡的接口事件。既然都不支持冒泡,那又如何实现事件代理呢?

可以换个角度,逆向思维,尝试事件捕获(Event Capturing,除了IE,现在流行的标准浏览器均支持)。

测试后会发现,如果你捕获 focus 或 blur 事件,目标元素的祖先元素均执行事件函数。至于为什么?或许是实现的一个 BUG。

el.addEventListener('focus', focusHandler,true);
el
.addEventListener('blur', blurHandler,true);

那对于 IE ,我们如何实现呢?

非常幸运,IE 下支持 focusin 和 focusout 事件,非常类似于 focus 和 blur 事件,唯一不同的是,这两种事件支持事件冒泡(Event Bubbling)。

el.onfocusin = focusHandler;
el
.onfocusout = blurHandler;

很完美的解决方案:

if(document.addEventListener){
    el
.addEventListener('focus', focusHandler,true);
    el
.addEventListener('blur', blurHandler,true);
}else{
    el
.onfocusin = focusHandler;
    el
.onfocusout = blurHandler;
}

当你下次看到 YUI 2.8 的 event/event-debug.js 源码中下面几段代码时,一定会清晰很多:

576    // String constants used by the addFocusListener and removeFocusListener methods
577
578     FOCUSIN ="focusin",
579     FOCUSOUT ="focusout";

       
....

750     _specialTypes:{
751         focusin:(isIE ?"focusin":"focus"),
752         focusout:(isIE ?"focusout":"blur")
753      },

       
....

1053    addListener:function(el, sType, fn, obj, overrideContext){
1054
1055        var capture =((sType == FOCUSIN || sType == FOCUSOUT)&&!YAHOO.env.ua.ie)?true:false;
1056
1057        returnthis._addListener(el,this._getType(sType), fn, obj, overrideContext, capture);
1058
1059    },
posted @ 2013-03-16 23:08  {前端开发}  阅读(906)  评论(0编辑  收藏  举报