2017-04-17 jQuery 原理

2017-04-17  本文已影响0人  GodlinE

jQuery 的内部实现

(function(){
        //1.定义构造函数
        var szjQuery = function(selector){
                //内部 new 了一个对象返回给外界,让外界使用方便,没必要再创建
                return new szjQuery.prototype.init(selector);
        }
        //2.修改函数的原型
        //以后,可以在这个位置扩展一些属性,或者方法
        //注意:这里有个比较重要的方法 init 方法,基本上所有的创建 jQuery 对象初始化的逻辑,都是在这个函数里面进行处理的
        szjQuery.prototype = {
                szjQuery:'1.1.0',
                selector:'',
                length:0,
                constructor:szjQuery,
                init:function(){
                        //this.length = 0;
                        //在这里处理 selector 传进来的参数
                        //1.特殊字符 ‘’ null undefined NaN 0 false
                        if(!selector){
                                return this;
                        } 
                        //2.判断是否是字符串
                        if($.isString(selector)){
                                //2.1要不就是代码片段,去空格处理
                                var result = $.trimString(selector);
                                if($.isHTML(result)){
                                        var tag = document.createElement('div');
                                        tag.innerHTML = selector;
                                        var firstChildren = tag.children;
                                        //call  apply 作用重新控制 this 指向,此处可以使用遍历然后控制 this[i] = firstChildren[i] 来实现
                                        [].push.apply(this,firstChildren);
                                        return this;
                                }
                                //2.2要不就是选择器
                                var tags = document.querySelectorAll(selector);
                                [].push.apply(this,tags);
                                return this;      
                        } 
                        //3.判定是否是伪数组/真数组
                        if($.isWindow(selector) && $.isLikeArray(selector)){
                                [].push.apply(this,selector);
                                return this;    
                        } 
                        //4.判断是否是一个函数
                        if($.isFunction(selector)){
                                $.ready(selector);
                        } 
                        //其他
                        //DOM 基本对象 基本数据类型 1234
                        this[0] = selector;
                        this.length = 1;
                        return this;                    
                }        
        };
        //3.创建一个快速批量创建静态方法/实例方法的方法
        //因为内部的 this ,是动态指向调用者的
        //所以,可以借助这个特性,来动态的给对象或者方法添加方法
        szjQuery.extend = szjQuery.prototype.extend = function(funDic){
                for(var key in funDic){
                        this[key] = funDic[key];
                }        
        }
        //4.重新修改 init 函数的原型指向,避免方法调用不到的问题
        //此处必须了解以下几点
        //4.1每个函数都有对应的原型对象
        //4.2通过什么构造函数,创建出来的实例对象,这个对象的 __proto__ 就指向该构造函数的原型对象
        //4.3当调用一个对象方法的时候,是根据 __proto__ 来进行查找方法的
        //4.4所以,当一个对象找不到方法,应该注意查看该对象的构造函数的
        //4.5注意,任何一个函数的原型,都可以修改
        szjQuery.prototype.init.prototype = szjQuery.prototype;
        //通过 window 对象,将内部对象暴露给外界
        //因为,基本上,所有的功能都是依附于 jQuery 对象存在的
        //所以,可以jQuery 对象给外界,然后其他的信息,会被间接的暴露出去
        window.szjQuery = window.$ = szjQuery;
        //6.扩展静态方法
        //工具类,判断类的是否是字符串,是否是对象等等
        szjQuery.extend({
               //是否是字符串方法
               'isString':function(){
                        return typeof str === 'string';
                },
                //可以压缩字符串的首尾空格
                //此处注意兼容,以及正则表达式的使用
                'trimString':function(str){
                        if(str.trim){
                                return str.trim();
                        }
                        return str.replace(/^\s+|\s+$/g, '');
                },
                //判断是否是窗口过对象
                'isWindow': function(w){
                        return window.window !== w;
                },
                //是否是伪数组
                'isLikeArray':function(){
                        return (this.isObject(arr) && 'length' in arr && (arr.length - 1) in arr);
                },    
                //是否是对象
                'isObject':function(obj){
                        return typeof obj === 'object';
                },
                //是否是代码片段
                //注意空格的容错处理
                'isHTML':function(html){
                        return html.charAt(0) === '<' && html.charAt(html.length - 1) === '>' &&html.length > 3
                },
                //是否是函数
                'isFunction':function(fun){
                        return typeof fun === 'function';
                },
                //是否是 DOM 对象
                'isDOM':function(dom){
                        if('nodeType' in dom){
                                return true;
                        }
                        return false;
                },
                //入口函数的处理
                //需要注意执行时机,以及执行次数
                'ready':function(func){
                        if(!$.isFunction(func)){
                                return;
                        }
                        //1.判断当前文档是否已经加载完毕
                        //直接执行
                        //document.readyState 可以兼容当前所有主流浏览器
                        var state = document.readyState;
                        if(state === 'complete'){
                                func();
                                return;
                        }
                        //2.如果没有加载完毕
                        //监听 DOM 树建立完成
                        // IE9+
                        if(document.addEventListener){
                                document.addEventListener('DOMContentloaded',func);
                                return;
                        }
                        // IE8
                        document.attachEvent('onreadystatechange',function(){
                                var state = document.readyState;
                                if(state === 'complete'){
                                        func();
                                }
                        });
                }
        });
//扩展实例方法
//数组相关的一些方法
//比如转换称为数组,遍历,切割数组等等
//此处需要掌握,数组操作的常用方法的内部实现
szjQuery.prototype.extend({
        //将伪数组,转换成为真数组
        'toArray':function(){
                var result = [].slice.call(this);
                return result;
          //
            // begin = begin === undefined ? 0 : begin;
            // end = (end === undefined || end > this.length) ? this.length: end;
            //
            // var tmpArr = [];
            // for (var i = begin; i < end; i++) {
            //     tmpArr.push(this[i]);
            // }
            //
            // return tmpArr;
        },
        //7.2获取某个一个 DOM 元素
        //注意正负索引值的处理
        'get':function(index){
                if(index === undefined){
                        return this.toArray();
                }
                index = index >=0?index:index + this.length;
                return this[index];
            // if (index >= 0) {
            //     return this[index];
            // }
            // // -1 +
            // index = index + this.length;
            // return this[index];
        },
        //7.3获取指定的 DOM 元素,包装的 jQuery 对象
        //可以考虑,借助其他已经实现过的方法,进行处理
        //因为,内部的逻辑大致和 get 方法类似
        'eq':function(index){
                if(index === undefined){
                        return $('');
                }
                return $(this.get(index));
        },
        //7.4获取第一个的 DOM 元素,包装的 jQuery 对象
        //可以考虑,借助其他已经实现国的方法,进行处理
        //因为,内部的逻辑,大致和 get 方法类似
        'first':function(){
                return this.eq(0);
        },
        //7.5 获取最后一个的 DOM 元素,包装 jQuery 对象
        //可以考虑,借助其他已经实现的方法,进行处理
        //因为,内部的逻辑,大致和 get  方法类似
        'last':function(){
                return this.eq(-1);
        },
        //[].splice 获取的是方法实现
        //7.6一定要注意,jQuery 对象里面的,这些方法的实现,其实和数组的这些方法实现一模一样
        //所以,此处,可以直接把数组对应方法的实现放在这里
        //这样,到时候,外界调用的时候,就会按照相同的操作数组的逻辑,来操作 jQuery 对象
        'splice':[].solice,
        'push':[].push,
        'sort':[].sort,
        'each':function(func){
                $.each(this,func);
        },
        'reverse':function(){
                var result = [];
                for(var i = this.length - 1 ; i >= 0;i--){
                       result.push(this[i]);                     
                }
                return $(result);
        }
});
//8.静态方法
//数组相关
szjQuery.extend({
        //8.1 遍历数组,或者伪数组,或者对象
        //内部注意不同类型的处理
        //还有就是,此方法,支持对象方法,和静态方法
        //一般碰到这种情况,我们优先开发静态方法,然后再在实例方法中,调用静态方法实现即可
        'each':function(obj,func){
                if($.isLikeArray(obj)){
                        for(var i = 0;i < obj.length;i++){
                                //func(i,obj[i]);
                                var isContinue = func.call(obj[i],i,obj[i]);
                                //isContinue = isContinue !== undefined ? isContinue : true;
                                if(isContinue === undefined){
                                        isContinue = true;
                                }
                                if(!isContinue){
                                        return;
                                }
                        }
                        return;
                }
                //不是伪数组
                if($.isObject(obj)){
                        for(var key in obj){
                                //func(key,obj[key]);
                                var isContinue = func.call(obj[key],key,obj[key]);
                                isContinue = isContinue !== undefined ? isContinue:true;
                                if(!isContinue){
                                        return;
                                }
                        }
                }
        },
        //8.2可以将一个字符串的空格,都给亚索,然后把里面的有效元素,存储到一个数组中
        //可以用来做一些格式化的操作
        'trimSpaceArrayWithStr':function(str){
                var resultArray = [];
                var temp = str.split(' ');
                for(var i = 0 ; i < temp.length;i++){
                        var value = temp[i];
                        if(value.length > 0){
                                resultArray.push(value);
                        }
                }
                return resultArray;
        }
});
//DOM 操作的相关方法
//注意:如果想要仿照一个功能
//先对这个功能进行充分的测试
//报错参数 参数个数 参数类型 返回值等信息
szjQuery.prototype.extend({
        //9.1 清空 DOM 对象里面的内容
        'empty':function(){
                this.each(function(){
                        //index value  value
                        //this 就是每一个 DOM 对象
                        this.innerHTML = '';
                });
                return this;
        },
        //9.2 删除指定的 DOM 对象
        'remove':function(){
                this.each(function(){
                        //this 是每一个 DOM 对象
                        this.parentNode.removeChild(this);
                });
                return this;
        },
        //9.3获取指定元素的 html 内容
        'html':function(content){
                if(content === undefined){
                        return this.get(0).innerHTML;
                }
                this.each(function(){
                        this.innerHTML = content;
                });
                return this;
        },
        //9.3 获取指定元素的 text 内容
        'text':function(content){
                if(content === undefined){
                        var resultStr = '';
                        this.each(function(){
                                resultStr += this.innerText;
                        });
                        return resultStr;
                }
                if($.isFuntion(content)){
                        this.each(function(index,value){
                                this.innerText = content(index,this.innerText)
                        });
                        return this;
                }
                this.each(function(){
                        this.innerText = content;
                });
                return this;
        },
        //9.4追加元素到另外一个元素中
        //下面几个方法类似
        //注意,测试先后顺序,分清插入的位置即可
        //注意核心代码的实现,然后再扩展业务逻辑
        'appendTo':function(content){
                content = $(content);
                var source = this;
                var target = content;
                target.each(function(t_index,t_value){
                        source.each(function(s_index,s_value){
                                if(t_index == 0){
                                        t_value.appendChild(s_value);
                                }else{
                                        var clone = s_value.cloneNode(true);
                                        t_value.appendChild(clone);
                                }
                        })
                });
                return this;
        },
        ‘prependTo’:function(content){
                content = $(content);
                var source = this;
                var target = content;
                target.each(function(t_index,t_value){
                        source.reverse().each(function(s_index,s_value){
                                  if(t_index == 0){
                                          //t_value.appendChild(s_value);
                                          t_value.inertBefore(s_value,t_value.firstChild);
                                  }else{
                                          var clone = s_value.cloneNode(true);
                                          //t_value.appendChild(clone);
                                          t_value.insetBefore(clone,t_value.firstChild);
                                  }
                          })
                });
                return this;
        },
        'prepend':function(content){
                if($.isObject(content)){
                      var source = content;
                      var target = this;
                      source.prependTo(target);
                      return this;          
                }
                this.each(function(){
                        // this == DOM 对象
                        this.innerHTML = content + this.innerHTML;
                });
                return this;
        },
        'append':function(content){
                if($.isObject(content)){
                        var source = content;
                        var target = this;
                        source.appendTo(target);
                        return this;
                }
                this.each(function(){
                        //this == DOM 对象
                        this.innerHTML = this.innerHTML + content;
                });
                return this;
        }
});
//10.DOM 样式的获取
//注意浏览器兼容
//此处需要掌握:了解样式的分类,以及基本的获取方式
szjQuery.extend({
        'getStyle':function(dom){
                if($.isDOM(dom)){
                        var finalStyle = dom.currentStyle ? dom.currentStyle : window.getComputedStyle(dom,null);
                        return finalStyle;
                }
        }
});
/*
*11.DOM 节点属性的操作
*包括,操作属性,操作节点属性,修改/获取 CSS 样式
*获取/设置 value 值
*判断类,新增、删除、切换类
*事件添加和移除
*注意:
*此段代码的开发,思路如下
*1.需要考虑核心的代码是什么?
*2.大部分都是批量操作,所以,从小工能开始实现,然后慢慢按照需求进行扩展
*3.千万不要一次性的从最大的功能开始左
*4.不要求实现的一模一样,只需要直到一个大概逻辑,有个简单基本实现就好
*5.容错性逻辑,最后统一处理,放置我们观察主要逻辑
*6.关于一些类名的判断,全部都是靠字符串之间的关系进行处理
*注意容错
*/
szjQuery.prototype.extend({
        //操作节点属性
        'attr':function(){
                if(arguments.length === 1){
                        var value = arguments[0];
                        //1.如果是字符串
                        if($.isString(value)){
                                //获取第一个 DOM 对象的对应的节点属性值
                                return this[0].getAttribute(value);
                        }
                        //2.如果是对象
                        if($.isObject(value)){
                                //批量的设置 DOM 对象里面的节点属性值
                                this.each(function(index,dom){
                                        $.each(value,function(key,value){
                                                dom.setAttribute(key,value);
                                        })
                                });
                                return this;     
                        }
                }
                //arguments,this,return
                if(arguments.length === 2 && $.isString(arguments[0])){
                        var key = arguments[0];
                        var value = arguments[1];
                        //遍历所有的 DOM 对象
                        this.each(function(index,dom){
                                dom.setAttribute(key,value);
                        });
                        return this;
                }
                throw '请输入正确的参数';
        },
        'removeAttr':function(){
                var firstParam = arguments[0];
                if($.isString(firstParam)){
                        this.each(function(index,dom){
                                dom.removeAttribute(firstParam);
                        })
                }
                return this;
        },
        'prop':function(){
                if(arguments.length === 1){
                        var value = arguments[0];
                        //1.如果是字符串
                        if($.isString(value)){
                                //获取第一个 DOM 对象的对应的属性值
                                return this[0][value];
                                //this['name'];
                                //this.name
                        }
                        //2.如果是对象
                        if($.isObject(value)){
                                //批量的设置 DOM 对象里面的属性值
                                this.each(function(index,dom){
                                        $.each(value,function(key,value){
                                                dom[key] = value;
                                        })
                                })
                                return this;
                        }
                }
                if(arguments.length === 2 && $.isString(arguments[0])){
                        var key = arguments[0];
                        var value = arguments[1];
                        //遍历所有的 DOM 对象
                        this.each(function(index,dom){
                                dom[key] = value;
                        });
                        return this;
                }
                throw '请输入正确的参数';
        },
        'removeProp':function(){
                var firstParam = arguments[0];
                if($.isString(firstParam)){
                        this.each(function(index,dom){
                                delete dom[firstParam];
                        })
                }
                return this;
        },
        'CSS':function(){
                if(arguments.length === 1){
                        var value = arguments[0];
                        //1.如果是字符串
                        if($.isString(value)){
                                //value == background width
                                //获取第一个 DOM 对象里面的样式属性
                                var dom = this[0];
                                return $.getStyle(dom)[value];
                        }
                        //2.如果是对象
                        if($is.Object(value)){
                                //批量的设置 DOM 对象里面的批量样式属性值
                                this.each(function(){
                                        $.each(value,function(index,dom){
                                                //dom.setAttribute(key,value);
                                                dom.style[key] = value;
                                        })
                                });
                                return this;
                        }
                }
                if(arguments.length === 2 && $.isString(arguments[0])){
                        var key = arguments[0];
                        var value = arguments[1];
                        //遍历所有的 DOM 对象
                        this.each(function(index,dom){
                                dom.style[key] = value;
                        });
                        return this;
                }
                throw '请输入正确的参数';
        },
        'val':funciton(firstParam){
                if(firstParam === undefined){
                        var dom = this[0];
                        //return dom.getAttribute('value');  这种写法是错误的无法实时获取更新了的数值
                        return dom['value'];
                }else{
                        //批量的给所有的 DOM 对象,赋值 value
                        this.each(function(index,dom){
                                dom['value'] = firstParam;
                        });
                        return this;
                }
        },
        ‘hasClass’:function(firstParam){
                if(firstParam === undefined){
                        return false;
                }
                // 'box111' 'box1' '  box1'
                // ' box1 ' 
                if($.isString(firstParam)){
                        var trimClassName = ' ' + $.trimString(firstParam) + ' ';
                        var hasClass = false;
                        this.each(function(index,dom){
                                var parentClassName = ' ' + $.trimString(dom.className) + ' ';
                                var searchIndex = parentClassName.indexOf(trimClassName);
                                  if(searchIndex >= 0){
                                            hasClass = true; 
                                            //结束遍历
                                            return false'     
                                  }
                        });
                        return hasClass;
                }
        },
        'addClass':function(firstParam){
                if(firstParam === undefined){
                        return this;
                }
                if($.isString(firstParam)){
                        //1.遍历所有的 dom 对象
                        this.each(function(index,dom){
                                //先获取给定的类名数组
                                var classNameArr = $.trimSpaceArrayWithStr(firstParam);
                                $.each(classNameArr,function(index,className){
                                        if(!$(dom).hasClass(className)){
                                                dom.className = dom.className + ' ' + className;
                                        }
                                });
                                //格式化, dom 的类名
                                var resultClassNames = $.trimSpaceArrayWithStr(dom.className);
                                //按照指定的字符,链接所有的元素,-》字符串,就是 join 的作用
                                  dom.className = resultClassNames.join(' ');
                        });
                }
                return this;
        },
        'removeClass':function(firstParam){
                if(firstParam === undefined ){
                        //清空所有 DOM 对象里面的类名
                        this.each(function(index,dom){
                                dom.className = '';
                        });
                        return this;
                }
                //'box1 box2'
                //'box1'
                //'box1 box2'
                if($.isString(firstParam)){
                        //'box1'
                        //var searchClassName = ' ' + $.trimString(firstParam) + ' ';
                        //'   box1   box2  '
                        //['box1','box2']
                        var searchClassNames = $.trimSpaceArrayWithStr(firstParam);
                        //遍历所有的 DOM 对象
                        this.each(function(index,dom){
                                //判断 DOM 对象的 className,是否包含指定的类名
                                var parentClassName = ' ' + dom.className + ' ';
                                //针对于每一个 DOM 对象
                                //删除,一个类名 集合
                                $.each(searchClassNames,function(){
                                          //如果包含,则删除
                                          if($(dom).hasClass(searchClassName)){
                                                  parentClassName = parentClassName.replace(searchClassName,'
 ');
                                          }
                                  });
                                  //代表该删除的,已经删除完毕
                                  //dom.className = parentClassName;
                                  //['box1','box2','box3']
                                  //'box1 box2 box3'
                                  var classNameArr = #.trimSpaceArrayWithStr(parentClassName);
                                  dom.className = classNameArr.join(' ');
                        })
                }
                return this;
        },
        'toggleClass':function(firstParam){
                if(firstParam  === undefined){
                        this.each(function(index,dom){
                                if(dom.className.length > 0){
                                        //永远有值
                                        dom['orginClassName'] = dom.className;
                                }
                                //格式化 className
                                var resultClassName = dom.className === ' ' ? dom['orginClassName'] : ' ';
                                dom.className = $trimSpaceArrayWithStr(resultClassName).join(' ');        
                        });
                        return this;
                }
                if($.isString(firstParam)){
                        //firstParam == '   box1   box2 '
                        var searchClassNames = $.trimSpaceArrayWithStr(firstParam);
                        //firstParam == 'box1'
                        //让每一个 DOM 对象,都切换给定的类名
                        this.each(function(index,dom){
                                  $.each(searchClassName,function(index,searchClassName){
                                        //判断是否有这个类名
                                        //有就删除没有就添加
                                        if($(dom).hasClass(searchClassName)){
                                                $(dom).removeClass(searchClassName);
                                        }else{
                                                $(dom).addClass(searchClassName);
                                        }
                                })
                        });
                        return this;
                }
        }
});
/*
*12 添加基本的事件监听和移除方法
*注意浏览器的兼容
*以及以后开发工具类的时候,工具类方法的类型
*是选择对象方法,还是使用静态方法
*主要区分依据,就是看下在方法内部是否可以借助 this 对象中的属性获取其他信息
*如果不需要,则统一使用静态方法进行实现
*/
$.extend({
        'addEvent':function(ele,type,func){
                //0.容错处理
                if(!$.isDOM(ele) || !$.isString(type) || isFunction(func)){
                        return;
                }
                //1.根据传递过来的参数,进行事件的监听
                if(ele.addEventListener){
                        ele.addEventListner(type,func)
                }else{
                        ele.attachEvent('on' + type ,func)
                }
                return;
        },
        'removeEvent':function(ele,type,func){
                if(!$.isDOM(ele) || $.isString(type) || $.isFunction(func)){
                        return;
                }
                //1.根据传递过来的参数,进行事件的监听
                if(ele.removeEventListener){
                        ele.removeEventListener(type,func);         
                }else{
                        ele.detachEvent('on' + type,func);
                }
                return;
        }
});
/*
*13.批量操作事件绑定,和事件解绑的方法
*此处注意开发步骤
*先从最基本,最小的功能开始左
*比如可以先看下一个 dom 对象,添加一个事件类型,绑定一个回调函数的时候是如何实现的
*然后慢慢进行扩展多个类型的
*多个回调函数的
*多个 DOM 对象的
*以此类推
*/
$.prototype.extend({
        //一个类型,一个回调函数,多个DOM 对象的情况
        '_on':function(type,func){
                //批量给 DOM 对象,添加事件
                this.each(function(index,dom){
                        $.addEvent(dom,type,func)
                })
        },
        //多个类型,一个回调函数,多个 DOM 对象的情况
        '_on2':function(types,func){
                //批量给 DOM 对象,添加事件
                var typeArray = $.trimSpaceArrayWithStr(types);
                this.each(function(index,type){
                        $.each(typeArray,function(index,type){
                                $.addEvent(dom,type,func)
                        })
                })
        },
        //多个类型,多个回调函数,多个 DOM 对象的情况
        '_on3':function(firstParam){
                //当事件绑定的时候
                if(arguments.length === 1){
                        if(!$.isObject(firstParam)){
                                return this;
                        }
                        this.each(function(index,dom){
                                $.each(firstParam,function(type,func){
                                        $.addEvent(dom,type,func);
                                })
                        });
                        return this;
                }
                if(arguments.length === 2){
                        //'click dbclick mouseover',func
                        //批量给 DOM 对象,添加事件
                        var typeArray = $.trimSpaceArrayWithStr(arguments[0]);
                        var func = arguments[1];
                        this.each(function(index.dom){
                                $.each(typeArray,function(index,type){
                                          $.addEvent(dom,type,func);
                                  })
                        })
                }
        },
        //为了存储,监听的事件信息,方便解绑
        'on':function(firstParam){
                //当事件绑定的时候,把这个 DOM 对象身上的事件类型,和事件回调都给记录下来
                if(arguments.length === 1){
                        if(!$.isObject(firstParam)){
                                return this;
                        }
                        this.each(function(index,dom){
                                //1.给 dom, 新增一个属性
                                dom['eventCache'] = dom['eventCache'] || [];
                                $.each(firstParam,function(type,func){
                                          $.addEvent(dom,type,func);
                                          dom['eventCache'][type] = dom['eventCache'][type] || [];
                                          dom['eventCache'][type].push(func);
                                  })
                        });
                        return this;
                }
                if(arguments.length ===2){
                        var typeArray = $.trimSpaceArrayWithStr(argument[0]);
                        var func = arguments[1];
                        this.each(function(index,dom){
                                dom['eventCache'] = dom['eventCache'] || [];
                                $.each(typeArray,function(index,type){
                                        $.addEvent(dom,type,func);
                                        dom['eventCache'][type] = dom['eventCache'][type] || [];
                                        dom['eventCache'][type].push(func);
                                })
                        })
                }
        },
        //解绑多个 DOM 对象,一个事件类型的情况
        '_off':function(type){
                //type === 'click'
                this.each(funcntion(index,dom){
                        var funcs = dom['eventCache'][type];
                        $each(funcs,function(index,func){
                                $.removeEvent(dom,type,func);
                        })
                });
                return this;
        },
        //解绑多个 DOM 对象,多个事件类型的情况
        '_off2':function(types){
                var typeArr = $.trimSpaceArrayWithStr(types);
                this.each(function(index,dom){
                          $.each(typeArr,function(index,type){
                                  //找到类型对应的回调函数组
                                  var funcs = dom['eventCache'][type];
                                  //解绑函数
                                  $.each(funcs,function(index,func){
                                          $.removeEvent(dom,type,func)
                                  })
                          })
                });
                return this;
        },
/*
*解绑多个DOM 对象,一个事件类型 指定回调函数的情况
*注意:吃出的开发,需要结合 on 方法内部,先记录下,当前对象绑定的事件信息
*/
                'off': function (types, paramFunc) {
            //  type === 'click'
            var typeArr = $.trimSpaceArrayWithStr(types);

            // 遍历所有的DOM对象
            this.each(function (index, dom) {
                console.log(dom['eventCache']);
                // 遍历所有的事件类型
                $.each(typeArr, function (index, type) {
                    // 找到类型对应的回调函数数组
                    var funcs = dom['eventCache'][type];

                    // 解绑函数
                    // 遍历所有的函数
                    $.each(funcs, function (index, func) {

                        // 处理指定函数这个参数没有传递的情况
                        if (paramFunc === undefined) {
                            $.removeEvent(dom, type, func);
                        }
                        // 处理指定函数 这个参数传递的情况
                        if (func === paramFunc) {
                            // 解绑
                            $.removeEvent(dom, type, func);
                        }
                    })
                })
            });
            return this;

        }
})
})(window)

上一篇下一篇

猜你喜欢

热点阅读