jQuery为我们提供了一个非常丰富好用的事件API,相对于浏览器自身的事件接口,jQuery有以下特点:

1. 对浏览器进行了兼容性处理,用户使用不需要考虑浏览器兼容性问题

2. 事件数据是保持在内部缓存中的,而不是保持在DOM节点上

3. 事件委托机制,提供了一个非常简单的事件委托使用方法

4. 自定义事件,不仅仅是浏览器事件,可以创建自定义事件

5. 辅助功能,比如命名空间,事件数据等等

那么下面就来看看jQuery是怎么实现的,首先扫一眼Event模块的源码结构:

彻底弄懂jQuery事件原理一

总共900行,总共包括5部分:

1. 正则和辅助函数:最上面的正则表达式和3个辅助函数,后面会说到

彻底弄懂jQuery事件原理一

 

2. event辅助类:用于事件处理的辅助对象

彻底弄懂jQuery事件原理一

 

3. Event可写事件对象,等同于浏览器事件中的event对象,但Event对象的数据是可写的,添加了jQuery的一些属性。

彻底弄懂jQuery事件原理一

 

4. 兼容性处理:事件的兼容性处理逻辑

彻底弄懂jQuery事件原理一

 

5. 对外API,添加到jquery实例对象的对外API

彻底弄懂jQuery事件原理一

这段代码结构逻辑上分为4层,

第一层是对外API,这段是对用户调用的参数处理

第二层是event辅助类,用户调用以后会调用辅助类的各种方法

第三层是Event对象,event处理过程中会创建Event对象来代替浏览器事件中的event对象

第四层是兼容性处理,针对浏览器中有些事件的兼容性问题,进行了处理 

 

1. 我们从对外API开始说起,比如:

<div id='div_main'>
    <div ></div>
</div>

<script>
    $("#div_main").on("click",function(){
        console.log(1);
    });
</script>

我们对$("#div_main")这个jquery对象调用了on方法,就可以注册一个点击事件,on方法是什么?见对外API那部分代码

 on: function(types, selector, data, fn, /*INTERNAL*/ one) {
            var origFn, type;

            // Types can be a map of types/handlers
            if (typeof types === "object") {
                // ( types-Object, selector, data )
                if (typeof selector !== "string") {
                    // ( types-Object, data )
                    data = data || selector;
                    selector = undefined;
                }
                for (type in types) {
                    this.on(type, selector, data, types[type], one);
                }
                return this;
            }

            if (data == null && fn == null) {
                // ( types, fn )
                fn = selector;
                data = selector = undefined;
            } else if (fn == null) {
                if (typeof selector === "string") {
                    // ( types, selector, fn )
                    fn = data;
                    data = undefined;
                } else {
                    // ( types, data, fn )
                    fn = data;
                    data = selector;
                    selector = undefined;
                }
            }
            if (fn === false) {
                fn = returnFalse;
            } else if (!fn) {
                return this;
            }

            if (one === 1) {
                origFn = fn;
                fn = function(event) {
                    // Can use an empty set, since event contains the info
                    jQuery().off(event);
                    return origFn.apply(this, arguments);
                };
                // Use same guid so caller can remove using origFn
                fn.guid = origFn.guid || (origFn.guid = jQuery.guid++);
            }
            return this.each(function() {
                jQuery.event.add(this, types, fn, data, selector);
            });
        },
on

相关文章: