彻底弄懂jQuery事件原理一

发布时间:2017-2-25 3:26:39 编辑:www.fx114.net 分享查询网我要评论
本篇文章主要介绍了"彻底弄懂jQuery事件原理一",主要涉及到彻底弄懂jQuery事件原理一方面的内容,对于彻底弄懂jQuery事件原理一感兴趣的同学可以参考一下。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

<div id='div_main'>    <div id="div_sub"></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

 这段代码其实是对用户调用的方法进行了各种参数情况逻辑判断,最后归根到jQuery.event.add方法,也就是最后是调用了event辅助类的方法,首先on方法对用户传入的参数进行了判断,主要可能有以下几种情况:

(1) 以json方式传入多个事件方法,比如:

on({"click":fn1,"blur":fn2},"li",data);
on({"click":fn1,"blur":fn2},data);

        //json对象格式
        if (typeof types === "object") {
         //selector不是字符串是数据,则重新设置数据变量,on({"click":fn1,"blur":fn2},data)
if (typeof selector !== "string") { data = data || selector; selector = undefined; }
         //对每个json属性递归调用on方法
for (type in types) { this.on(type, selector, data, types[type], one); } return this; }

(2)其他三种情况:on("click",fn) on("click","li",fn) on("click",data,fn)

            if (data == null && fn == null) {                // 类似on("click",fn1),重置变量                fn = selector;                data = selector = undefined;            } else if (fn == null) {                if (typeof selector === "string") {                    //类似on("click","li",fn)                     fn = data;                    data = undefined;                } else {                    //类似on("click",data,fn);                    fn = data;                    data = selector;                    selector = undefined;                }            }
       //快捷方式,如果fn参数传入false,自动设置为false方法
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实例进行调用                jQuery.event.add(this, types, fn, data, selector);            });

然后是one方法,其实就是调用上面的on方法,带上one参数

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

off方法,和on方法类似,针对输入参数的几种情况最终是调用了event辅助类的remove方法。

 off: function(types, selector, fn) {            var handleObj, type;            if (types && types.preventDefault && types.handleObj) {                // ( event )  dispatched jQuery.Event                handleObj = types.handleObj;                jQuery(types.delegateTarget).off(                    handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType,                    handleObj.selector,                    handleObj.handler                );                return this;            }            if (typeof types === "object") {                // ( types-object [, selector] )                for (type in types) {                    this.off(type, selector, types[type]);                }                return this;            }            if (selector === false || typeof selector === "function") {                // ( types [, fn] )                fn = selector;                selector = undefined;            }            if (fn === false) {                fn = returnFalse;            }            return this.each(function() {                jQuery.event.remove(this, types, fn, selector);            });        },

tigger方法,最终是调用event辅助类的tigger方法

        trigger: function(type, data) {            return this.each(function() {                jQuery.event.trigger(type, data, this);            });        },

triggerHandler方法,调用event类的方法

      triggerHandler: function(type, data) {            var elem = this[0];            if (elem) {                return jQuery.event.trigger(type, data, elem, true);            }        }

tiggerHandler和tigger方法的区别是,triggerHandler只执行jQuery对象数组中的第一个对象,并且不执行冒泡,不执行浏览器默认事件。

上一篇:angular2 问题请教
下一篇:初始化模块,很好的一种写法.

相关文章

相关评论

本站评论功能暂时取消,后续此功能例行通知。

一、不得利用本站危害国家安全、泄露国家秘密,不得侵犯国家社会集体的和公民的合法权益,不得利用本站制作、复制和传播不法有害信息!

二、互相尊重,对自己的言论和行为负责。