JavaScript思維導圖——Day 36(jQuery之工具方法之回調對象)

在這裏插入圖片描述

(function () {
    function jQuery(selector) {
        return new jQuery.prototype.init(selector); // init的原型鏈上有css的方法
    }
    jQuery.prototype.init = function (selector) {
        // var this = {}
        // 選出 dom 標籤 並且包裝成jQuery對象 返回
        // id class
        this.length = 0;
        // null undefined
        if (selector == null) {
            return this;
        }
        if (typeof selector == 'string' && selector.indexOf('.') != -1) {
            var dom = document.getElementsByClassName(selector.slice(1));
        } else if (typeof selector == 'string' && selector.indexOf('#') != -1) {
            var dom = document.getElementById(selector.slice(1));
        }
        if (selector instanceof Element || dom.length == undefined) { // 只有一個dom
            this[0] = dom || selector;
            this.length++;
        } else { // 你有很多個dom Elements
            // 循環dom
            for (var i = 0; i < dom.length; i++) {
                this[i] = dom[i] || selector[i];
                this.length++;
            }
        }
        // return this;
    }

    jQuery.prototype.css = function (config) {
        // 循環操作每一個dom
        for (var i = 0; i < this.length; i++) {
            for (var attr in config) {
                this[i].style[attr] = config[attr]; // 這裏如果加了px那麼就只能修改像素值了 對於顏色透明度就會使其失效
            }
        }
        return this; // 鏈式操作的精髓 又返回了一個函數本身
    }

    jQuery.prototype.pushStack = function (dom) {
        // dom newObject
        if (dom.constructor != jQuery) {
            dom = jQuery(dom);
        }
        dom.prevObject = this;
        return dom;
    }

    jQuery.prototype.get = function (num) {
        return num == null ? [].slice.call(this, 0) : num >= 0 ? this[num] : this[num + this.length];
    }

    jQuery.prototype.eq = function (num) {
        var dom = num == null ? null : num >= 0 ? this[num] : this[num + this.length];
        return this.pushStack(dom);
    }

    jQuery.prototype.add = function (selector) {
        var curObj = jQuery(selector);
        var baseObj = this;
        var newObject = jQuery();
        for (var i = 0; i < curObj.length; i++) {
            newObject[newObject.length++] = curObj[i];
        }
        for (var i = 0; i < baseObj.length; i++) {
            newObject[newObject.length++] = baseObj[i];
        }
        //  newObject.prevObject = this;
        this.pushStack(newObject);

        return newObject;
    }

    jQuery.prototype.end = function () {
        return this.prevObject;
    }
    jQuery.prototype.myOn = function (type, handle) {
        for (var i = 0; i < this.length; i++) {
            if (!this[i].cacheEvent) {
                this[i].cacheEvent = {};
            }
            if (!this[i].cacheEvent[type]) {
                this[i].cacheEvent[type] = [handle];
            } else {
                this[i].cacheEvent[type].push(handle);
            }
        }
    }

    jQuery.prototype.myTrigger = function (type) {
        var self = this;
        var params = arguments.length > 1 ? [].slice.call(arguments, 1) : [];
        for (var i = 0; i < this.length; i++) {
            if (this[i].cacheEvent[type]) {
                this[i].cacheEvent[type].forEach(function (ele, index) {
                    ele.apply(self, params)
                });
            }
        }
    }

    // 創建隊列
    jQuery.prototype.myQueue = function () {
        var queueObj = this;
        var queueName = arguments[0] || 'fx'; // 默認隊列名稱爲'fx'
        var addFunc = arguments[1] || null;
        var len = arguments.length;
        // 獲取隊列
        if (len == 1) {
            return queueObj[0][queueName];
        }
        // queue dom {chain :} 添加隊列 往已有隊列push內容
        queueObj[0][queueName] == undefined ? queueObj[0][queueName] = [addFunc] : queueObj[0][queueName].push(addFunc);
        return this;
    }

    jQuery.prototype.myDelay = function (duration) {
        var queueArr = this[0]['fx'];
        queueArr.push(function (next) {
            setTimeout(function () {
                next();
            }, duration);
        })
        return this;
    }

    jQuery.prototype.myDequeue = function () {
        var self = this;
        var queueName = arguments[0] || 'fx';
        var queueArr = this.myQueue(queueName);
        var currFunc = queueArr.shift(); // 去掉數組第一個
        if (currFunc == undefined) {
            return;
        }
        var next = function () {
            self.myDequeue(queueName); // 拿第一個執行 再調用第一個
            // 防止鏈式調用時 丟失this 把this保存起來一直執行
        }
        currFunc(next);
        return this;
    }

    // json 是目標對象
    jQuery.prototype.myAnimate = function (json, callBack) {
        var len = this.length;
        var self = this;
        var baseFunc = function (next) {
            var times = 0;
            for (var i = 0; i < len; i++) {
                stratMove(self[i], json, function () {
                    times++;
                    if (times == len) {
                        callBack && callBack();
                        next();
                    }
                });
            }
        }
        this.myQueue('fx', baseFunc);
        // 出隊操作
        if (this.myQueue('fx').length == 1) {
            this.myDequeue('fx'); // 立馬執行
        }

        function getStyle(dom, atter) {
            if (window.getComputedStyle) {
                return window.getComputedStyle(dom, null)[atter];
            } else {
                return dom.getComputedStyle[atter];
            }
        }

        function stratMove(dom, attrObj, callBack) {
            clearInterval(dom.timer);
            var isSpeed = null,
                iCur = null;
            dom.timer = setInterval(() => {
                var bStop = true;
                for (var attr in attrObj) {
                    if (attr == 'opacity') {
                        iCur = parseFloat(getStyle(dom, attr)) * 100;
                    } else {
                        iCur = parseInt(getStyle(dom, attr));
                    }
                    isSpeed = (attrObj[attr] - iCur) / 7;
                    isSpeed = isSpeed > 0 ? Math.ceil(isSpeed) : Math.floor(isSpeed);
                    if (attr == 'opacity') {
                        dom.style.opacity = (iCur + isSpeed) / 100;
                    } else {
                        dom.style[attr] = iCur + isSpeed + 'px';
                    }
                    if (iCur != attrObj[attr]) {
                        bStop = false;
                    }
                }
                if (bStop) {
                    clearInterval(dom.timer);
                    console.log('over');
                    typeof callBack == 'function' && callBack();
                }

            }, 30);

        }
        return this;
    }

    jQuery.myCallbacks = function () {
        // once memory null
        // 存儲參數
        var opticons = arguments[0] || '';
        // 通過add來加入方法
        var list = [];
        // 記錄當期要執行函數的索引
        var fireIndex = 0;

        // 實參列表
        var args = [];

        //  證明有沒有fire過
        var fierd = false;

        var fire1 = function () {
            for (; fireIndex < list.length; fireIndex++) {
                list[fireIndex].apply(window, args);
            }
            if (opticons.indexOf('once') != -1) {
                list = [];
                fireIndex = 0;
            }
        }
        return {
            add: function (func) {
                list.push(func);
                if (opticons.indexOf('memory') != -1 && fierd) {
                    fire1();
                }
                return this;
            },
            fire: function () {
                fireIndex = 0;
                args = arguments;
                fierd = true;
                fire1();
            }
        }
    }

    jQuery.myDeferred = function () {
        // callback 實現的
        // 3 個callback done resolve fail reject progress notify
        var arr = [
            [
                jQuery.myCallbacks('oncememory'), 'done', 'resolve'
            ],
            [
                jQuery.myCallbacks('oncememory'), 'fail', 'reject'
            ],
            [
                jQuery.myCallbacks('memory'), 'progress', 'notify'
            ]
        ];
        var pendding = true;
        var deferred = {};
        for(var i = 0; i < arr.length;i ++){
            // arr[0]
            // 註冊
            deferred[arr[i][1]] =  (function(index){
                return function(func){
                    arr[index][0].add(func);
                }
            })(i)
            // 觸發
            deferred[arr[i][2]] = (function(index){
                return function(){
                    var args = arguments;
                    if(pendding){
                        arr[index][0].fire.apply(window,args);
                        arr[index][2] == 'resolve' || arr[index][2] == 'reject' ? pendding = false : '';
                    }   
                }
            })(i);
        }

        return deferred;

    }


    jQuery.prototype.init.prototype = jQuery.prototype; // init的原型鏈上有css的方法
    window.$ = window.jQuery = jQuery; // 內部jQuery的函數被保存到了window上所有沒有被釋放 就是閉包
})();
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章