图片描述

--- focusin、focusout focus、blur
冒泡支持 支持 不支持
浏览器支持 现在所有浏览器都支持,但以前firefox52以下不支持 所有浏览器都支持

注册focus事件

以下是经简化后zepto处理注册focus事件的代码。运行代码,可以观察到当input获得焦点时触发了form注册focus时的回调函数。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>foucus事件委派</title>
</head>
<body>
<div>
    <form action="" style="padding: 50px;background-color: #00b4fd;width: 200px;height: 200px">
        <input type="text" value="helloworld">
    </form>
</div>
</body>
<script>
    //除了IE,其他浏览器的window对象中都没有onfocusin属性,但是其他浏览器addEventListener('focusin')有效
    var focusinSupported = 'onfocusin' in window,
        form = document.forms[0],
        focus = {focus: 'focusin', blur: 'focusout'}

    function callback(event) {
         console.log(event.target.tagName)//INPUT
        console.log(event.type,event.bubbles)//event.bubbles为false表明当前事件不会向上冒泡
        this.style.background = "red"
    }

    //当type为focus且浏览器支持onfocusin,则focus -> focusin
    function realEvent(type) {
        return focusinSupported && focus[type] || type
    }

    function eventCapture() {
        //不支持onfocusin则在捕获阶段触发事件
        return !focusinSupported ? true : false
    }

    form.addEventListener(realEvent('focus'), callback, eventCapture());
//    form.addEventListener(realEvent('focus'), callback, false);//focus不会向上冒泡,这样写不会触发回调
</script>
</html>    

代码比较少,下面说一下重点。

zepto的处理focus事件注册流程大致如下

  • 为了有事件冒泡以完成事件委派,一般情况下zepto用focusin、focusout代替focus、blur
  • 在浏览器不支持focusin、focusout的情况下,只能用focus、blur在捕获阶段触发回调,间接做到事件委派。

IE9开始使用DOM事件模型,zepto统一用addEventListener注册事件,不支持IE9以下的版本,zepto中的on方法内部调用add方法,add方法经过多步处理,最后是这样注册一个事件的

form.addEventListener(realEvent('focus'), callback, eventCapture());

zepto是用以下方式来判断浏览器是否支持focusin事件

var focusinSupported = 'onfocusin' in window

除了IE,其他浏览器的window对象中都没有onfocusin属性,其他浏览器中focusinSupported为false,但其他浏览器也支持focusin,用addEventListener('focusin')是有效的。下表是zepto注册focus事件的两个重要判断

--- IE9+ FF、Chrome
realEvent focusinSupported:true, focus 转换为 focusin focusinSupported:false,focus 不作转换
eventCapture false,冒泡阶段触发回调 true,捕获阶段触发回调

在捕获阶段获取目标对象同样可以实现事件委派,原因可以参考以下引用

即使"DOM2级事件"规范明确要求捕获阶段不会涉及事件目标(作者注释:即event.target),但IE9、Safari、Chrome、Firefox 和 Opera9.5及更高版本都会在捕获阶段触发事件对象上的事件。结果,就是有两个机会在目标对象上面操作事件。

<<Javascript高级编程>>第三版 13.1.3 DOM事件流 p348

注册focusin事件

除了IE9-,在zepto中,其他主流浏览器都可以注册focusin事件

总结

现在所有浏览都已经支持foucsin,未来属于支持冒泡的focusin

参考


luobogor
522 声望34 粉丝