什么是事件代理(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        return this._addListener(el, this._getType(sType), fn, obj, overrideContext, capture);
1058
1059    },


共有17 条评论

  1. 1. 头像 CssRainbow

    怿飞,确实是一个细心的人,知识面广呀,我希望怿飞同学把《关于JavaScript的事件代理》作为一个专题,由浅入深的把更多的知识给大家分享一下,网上关于事件代理这方面的资料不是很丰富。

  2. 2. 如何在事件代理中正确使用 focus 和 blur 事件 | CssRainbow.cn

    [...] 怿飞的《如何在事件代理中正确使用 focus 和 blur 事件》文章。 [...]

  3. 3. 头像 天堂左我往右

    学习了,呵呵

  4. 4. 头像 Tianchao

    太强了!

  5. 5. 头像 Tianchao

    您的评论正在穿越伟大的GFW,哈哈

    怿飞也是个有趣的人!

  6. 6. 头像 kangre

    怿飞的学习都很广泛哦!!学识渊博~

  7. 7. 头像 rainoxu

    总是能在这里学到新东西:)

  8. 8. 头像 lianleif

    很受用,谢谢!学到一些东西

  9. 9. 头像 乐搜

    学到的东西不算少

  10. 10. 头像 Noman

    分析的很好,还是挺有帮助的,收藏了

  11. 11. 头像 ecosway

    学到了 谢谢

  12. 12. 头像 明河共影

    在jquery1.4中也引入新的二个事件来解决focus和blur无法冒泡的问题。分别是focusin和focusout。怿飞说的这个原理还是很正确的,赞一个。

  13. 13. 头像 明河共影

    同志,你有强制将所有评论者头像设置成一个路径?这头像有些抽象,O(∩_∩)O~呵呵。

  14. 14. 头像 jiemeng

    够技术的,没看懂

  15. 15. 头像 neeke

    先留名,慢慢看。

  16. 16. 头像 我不是高手

    忍不住又看了一遍

  17. 17. 头像 sam

    哎,看到怿飞的文章,真是觉得惭愧啊!自己的知道面太少了,还停留在用js实现各种花哨的功能上。

发表评论

(必填)

(必填,会为您保密)

评论仅支持“a、abbr、strong、em、blockquote、code”几个简单的标签