zoukankan      html  css  js  c++  java
  • 11.jQuery工具方法$.Callbacks()的简单实现

    jQuery工具方法$.Callbacks()的简单实现:

    (function () {
        //创建一个jQuery构造函数
        function jQuery(selector) {
            return new jQuery.prototype.init(selector);
        }
        //为jQuery的原型添加init属性,所有实例可以使用该属性
        jQuery.prototype.init = function (selector) {
            this.length = 0; //为this添加length属性,并且赋值为0
            //选出 dom 并且包装成jQuery对象返回
            //判断selector是null 和 undefined 和 dom对象 和 id 和 class的情况
            if (selector == null) { //判断selector是null或undefined
                return this;
            } else if (typeof selector === 'string' && selector.indexOf('.') != -1) { //selector是class的情况
                var dom = document.getElementsByClassName(selector.slice(1));
            } else if (typeof selector === 'string' && selector.indexOf("#") != -1) { //selector是id的情况
                var dom = document.getElementById(selector.slice(1));
            }
    
            if (selector instanceof Element || dom.length == undefined) { //(selector是dom对象) || (selector是id,返回的是一个对象,对象没有length属性)
                this[0] = dom || selector; //(selector是id) || (selector是dom对象)
                this.length++;
            } else { //selector是class,返回的是一个类数组
                for (var i = 0; i < dom.length; i++) {
                    this[i] = dom[i];
                    this.length++;
                }
            }
        };
    
        //为jQuery的原型添加css属性,所有实例可以使用该属性
        jQuery.prototype.css = function (config) {
            for (var i = 0; i < this.length; i++) {
                for (var prop in config) {
                    this[i].style[prop] = config[prop];
                }
            }
    
            return this; //链式调用的精髓
        };
    
        //为jQuery对象的prevObject属性赋值,从而可以使用end()方法
        jQuery.prototype.pushStack = function (dom) {
            //dom是jQuery对象
            if (dom.constructor != jQuery) { //dom是原生的dom对象
                dom = jQuery(dom); //将原生dom对象包裹成jQuery对象
            }
            dom.prevObject = this; //
    
            return dom;
        };
    
        //为jQuery的原型添加get属性,所有实例可以使用该属性
        jQuery.prototype.get = function (num) {
            //num == null 返回数组
            //num >= 0 返回this[num]
            //num < 0 返回this[length + num]
            return (num != null) ? ((num >= 0) ? (this[num]) : (this[num + this.length])) : ([].slice(this, 0));
        };
    
        //为jQuery的原型添加get属性,所有实例可以使用该属性
        jQuery.prototype.eq = function (num) {
            return this.pushStack(this.get(num)); //调用jQuery.prototype.get()函数获取到dom对象,再封装为jQuery对象并且为jQuery对象添加prevObject属性
        };
    
        //为jQuery的原型添加add属性,所有实例可以使用该属性
        jQuery.prototype.add = function (selector) {
            var curObj = jQuery(selector); //当前通过add添加的selector选中的jQuery对象
            var prevObj = this; //调用add()的jQuery对象
            var newObj = jQuery();
    
            for (var i = 0; i < curObj.length; i++) {
                newObj[newObj.length++] = curObj[i];
            }
    
            for (var i = 0; i < prevObj.length; i++) {
                newObj[newObj.length++] = prevObj[i];
            }
    
            this.pushStack(newObj); //为jQuery对象添加prevObject属性
    
            return newObj; //将合并后的jQuery对象返回
        };
    
        //为jQuery的原型添加end属性,所有实例可以使用该属性
        jQuery.prototype.end = function () {
            return this.prevObject; //直接返回前一个jQuery对象
        };
    
        //为jQuery的原型添加on属性,所有实例可以使用该属性
        jQuery.prototype.on = function (type, handle) {
            for (var i = 0; i < this.length; i++) {
                if (!this[i].cacheEvent) {//判断每一个原生dom对象中是否有事件
                    this[i].cacheEvent = {}; //为每一个原生的dom对象添加绑定事件
                }
                if (!this[i].cacheEvent[type]) {//判断每一个原生对象是否有type类型的绑定事件
                    this[i].cacheEvent[type] = [handle];//没有则为该类型事件添加处理函数数组
                } else {
                    this[i].cacheEvent[type].push(handle);//若已经有该类型事件,则直接放入数组
                }
            }
        };
    
        //为jQuery的原型添加trigger属性,所有实例可以使用该属性
        jQuery.prototype.trigger = function (type) {
            var self = this;//将调用trigger函数的jQuery对象存放在self中
            var params = arguments.length > 1 ? [].slice.call(arguments, 1) : [];//判断调用trigger()函数时是否传入除了type以外的其他参数
            for (var i = 0; i < this.length; i++) {//循环遍历this
                if (this[i].cacheEvent[type]) {//判断每个原生dom对象中是否存放有type类型的事件
                    this[i].cacheEvent[type].forEach(function (ele, index) {//有多个相同类型的事件时,要全部依次执行
                        ele.apply(self, params);//通过self调用事件,并且把参数传入
                    });
                }
            }
        };
    
        //为jQuery的原型添加queue属性,所有实例可以使用该属性
        jQuery.prototype.queue = function (type, handle) {
            var queueObj = this;//jQuery对象
            var queueName = arguments[0] || 'fx';//第一个形参,为队列名称
            var addFunc = arguments[1] || null;//第二个形参,是处理函数
            var len = arguments.length;//获取形参个数
    
            //若只传了一个参数type,则直接返回队列数组
            if(len == 1){
                return queueObj[0][queueName];
            }
    
            //取出jQuery中的dom对象,为dom对象添加队列事件
            queueObj[0][queueName] == undefined ? (queueObj[0][queueName] = [addFunc]) : (queueObj[0][queueName].push(addFunc));
            
            return this;
        };
    
        //为jQuery的原型添加dequeue属性,所有实例可以使用该属性
        jQuery.prototype.dequeue = function (type) {
            var self = this;
            var queueName = arguments[0] || 'fx';
            var queueArr = this.queue(queueName);
    
            var currFunc = queueArr.shift();
            if(currFunc == undefined){
                return ;
            }
    
            var next = function(){
                self.dequeue(queueName);
            }
    
            currFunc(next);
            return this;
        };
    
        //为jQuery添加Callbacks属性,jQuery可以使用该属性
        jQuery.Callbacks = function () {
            // 'once' 'memory' 'once memory' null
            
            var options = arguments[0] || '';// 存储参数
            //存储add来加入的方法
            var list = [];
    
            var fireIndex = 0;//记录当前要执行函数的索引
    
            var fired = false;//记录方法是否被fire过
    
            var args = [];//实际参数列表
    
            var fire = function(){
                for(; fireIndex < list.length; fireIndex++){
                    list[fireIndex].apply(window, args)
                }
                if(options.indexOf('once') != -1){
                    list = [];
                    fireIndex = 0;
                }
            }
    
            return {
                add: function(func){
                    list.push(func);
                    if(options.indexOf('memory') != -1 && fired){//参数是'memory' && 已经执行过fired
                        fire();//接着执行后面add的函数
                    }
                    return this;
                },
                fire: function(){
                    fireIndex = 0;
                    fired = true;//
                    args = arguments;
                    fire();
                }
            }
        };
    
        //上面的jQuery构造函数是new 一个jQuery.prototype.init对象,
        //jQuery.prototype.init对象上没有jQuery.prototype上的css()方法
        //所以添加下面一句,让jQuery.prototype.init对象可以调用jQuery.prototype上的css()方法
        jQuery.prototype.init.prototype = jQuery.prototype;
    
        //让外部可以通过$()或者jQuery()调用
        window.$ = window.jQuery = jQuery;
    }());
    myJquery.js

    调用$.Callbacks()方法:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body>
        <script src="./myJquery.js"></script>
        <script>
            var cb = $.Callbacks();
            function a(){
                console.log("a null");
            }
            function b(){
                console.log("b null");
            }
            cb.add(a);
            cb.add(b);
            cb.fire();
            cb.fire();
    
    
            var cb = $.Callbacks('once');
            function c(){
                console.log("c once");
            }
            function d(){
                console.log("d once");
            }
            cb.add(c);
            cb.add(d);
            cb.fire();
            cb.fire();
    
    
            var cb = $.Callbacks('memory');
            function e(){
                console.log("e memory");
            }
            
            cb.add(e);
            cb.fire();
            function f(){
                console.log("f memory");
            }
            cb.add(f);
            cb.fire();
        </script>
    </body>
    </html>
    index.html

    效果展示:

  • 相关阅读:
    85. Maximal Rectangle
    120. Triangle
    72. Edit Distance
    39. Combination Sum
    44. Wildcard Matching
    138. Copy List with Random Pointer
    91. Decode Ways
    142. Linked List Cycle II
    异或的性质及应用
    64. Minimum Path Sum
  • 原文地址:https://www.cnblogs.com/lanshanxiao/p/12897720.html
Copyright © 2011-2022 走看看