• jQuery 2.0.3 源码分析 事件体系结构


    那么jQuery事件处理机制能帮我们处理那些问题?

    1. 毋容置疑首先要解决浏览器事件兼容问题
    2. 可以在一个事件类型上添加多个事件处理函数,可以一次添加多个事件类型的事件处理函数
    3. 提供了常用事件的便捷方法
    4. 支持自定义事件
    5. 扩展了组合事件
    6. 提供了统一的事件封装、绑定、执行、销毁机制
    7. ……

    为了更深入的理解幕后的实现,所以先整理整体的结构思路,从1.7后就去除了live绑定,所以现在的整个事件的API

    如图:

    image


    jQuery的事件绑定有多个方法可以调用,以click事件来举例:

    • click方法
    • bind方法
    • delegate方法
    • on方法
    $('#foo').click(function(){ })
    
    $('#foo').bind('click',function(){ })
    
    $("foo").delegate("td", "click", function() { });
    
    $("foo").on("click", "td", function() { });

    以上四种绑定都能达到同一样的效果,但是各自又有什么区别,内部又是如何实现?


    源码分析

    click方式

    jQuery.each( ("blur focus focusin focusout load resize scroll unload 
    click
     dblclick " +
            "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
            "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) {
    
            // Handle event binding
            jQuery.fn[ name ] = function( data, fn ) {
                return arguments.length > 0 ?
                    this.on( name, null, data, fn ) :
                    this.trigger( name );
            };
        });

    源码很简单,合并15种事件统一增加到jQuery.fn上

    内部调用this.on / this.trigger

    bind方式

    bind: function( types, data, fn ) {
        return this.on( types, null, data, fn );
    },
    unbind: function( types, fn ) {
        return this.off( types, null, fn );
    },

    同样调用的this.on/this.off

    delegate方式

    delegate: function( selector, types, data, fn ) {
        return this.on( types, selector, data, fn );
    },
    undelegate: function( selector, types, fn ) {
        // ( namespace ) or ( selector, types [, fn] )
        return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn );
    }

    同样调用的this.on/this.off

    one方式

    one: function( types, selector, data, fn ) {
        return this.on( types, selector, data, fn, 1 );
    },

    还是this.on

    可见以上的接口只是修改了不同的传递参数,最后都交给on实现的


    实现最简单的事件委托

    给父元素绑定事件,子元素也能响应


     

    其实委托的原理都是一样的,通过事件对象过滤出关联目标的hack,做相对应的处理,那么JQuery是如何实现的呢?


    jQuery事件的流程图

    在绑定阶段与执行阶段

    image


     

    那么JQuery为了更好的对事件的支持内部又做了哪些额外的优化操作?

    兼容性问题处理:

    浏览器的事件兼容性是一个令人头疼的问题。IE的event在是在全局的window下, 而mozilla的event是事件源参数传入到回调函数中。还有很多的事件处理方式也一样

    JQuery提供了一个 event的兼容类方案

    jQuery.event.fix 对游览器的差异性进行包装处理

    例如:

    1. 事件对象的获取兼容,IE的event在是在全局的window,标准的是event是事件源参数传入到回调函数中
    2. 目标对象的获取兼容,IE中采用srcElement,标准是target
    3. relatedTarget只是对于mouseout、mouseover有用。在IE中分成了to和from两个Target变量,在mozilla中 没有分开。为了保证兼容,采用relatedTarget统一起来
    4. event的坐标位置兼容
    5. 等等

    事件的存储优化:

    jQuery并没有将事件处理函数直接绑定到DOM元素上,而是通过$.data存储在缓存$.cahce上,这里就是之前分析的贯穿整个体系的缓存系统了

    声明绑定的时候:

    • 首先为DOM元素分配一个唯一ID,绑定的事件存储在$.cahce[ 唯一ID ][ $.expand ][ 'events' ]上,而events是个键-值映射对象,键就是事件类型,对应的值就是由事件处理函数组成的数组,最后在DOM元素上绑定(addEventListener/ attachEvent)一个事件处理函数eventHandle,这个过程由 jQuery.event.add 实现。

    执行绑定的时候:

    • 当事件触发时eventHandle被执行,eventHandle再去$.cache中寻找曾经绑定的事件处理函数并执行,这个过程由 jQuery.event. trigger 和 jQuery.event.handle实现。
    • 事件的销毁则由jQuery.event.remove 实现,remove对缓存$.cahce中存储的事件数组进行销毁,当缓存中的事件全部销毁时,调用removeEventListener/ detachEvent销毁绑定在DOM元素上的事件处理函数eventHandle。

    事件处理器:

    jQuery.event.handlers

    针对事件委托和原生事件(例如"click")绑定 区分对待

    事件委托从队列头部推入,而普通事件绑定从尾部推入,通过记录delegateCount来划分,委托(delegate)绑定和普通绑定。

    其余一些兼容事件的Hooks

    fixHooks,keyHooks,mouseHooks


    总的来说对于JQuery的事件绑定

    在绑定的时候做了包装处理

    在执行的时候有过滤器处理

    下章就开始深入on内部实现的分析了

  • 相关阅读:
    使用哈工大LTP进行文本命名实体识别并保存到txt
    gpu命令cuda命令
    python路径拼接os.path.join()函数的用法
    pytorch利用多个GPU并行计算多gpu
    pytorch 多GPU训练总结(DataParallel的使用)
    解决 win10 pycurl安装出错 Command "python setup.py egg_info" failed with error code 10 编译安装包 安装万金油
    解决:"UnicodeEncodeError: 'ascii' codec can't encode character u'xa0' in position"错误
    windows下多版本python安装与pip安装和pip使用 吐血总结
    Python 能做什么?
    Oracle中的索引详解
  • 原文地址:https://www.cnblogs.com/aaronjs/p/3441320.html
Copyright © 2020-2023  润新知