Jquery底层封装

// jquery的所有对象都封装在闭包上
// 闭包防止全局变量污染


(function(){
    function jQuery(selector){
        return new jQuery.prototype.init(selector)
    }
    // 通过传进来的参数selector来查找元素,init为初始化的意思
    jQuery.prototype.init = function(selector){
        // this = {}
        this.length = 0;

        // null undefined dom
        if(selector == null){
            return this
        }
        // 根据selector参数选出对应的dom元素包装成一个对象进行返回
        // id class
        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) )//一个
        }

        // 如果传进来一个dom原生对象就不需要查找元素,直接把它放到返回的jquery对象中就好
        if(selector instanceof Element || dom.length == undefined){
            // id dom
            this[0] = dom || selector;
            this.length ++;
        }else{
            for(var i = 0;i < dom.length;i++){
                this[i] = dom[i]
                this.length ++;
            }
        }
        // return this;
    }

    jQuery.prototype.css = function(config){
        // this
        for(var i = 0;i < this.length;i++){
            for(var attr in config){
                this[i].style[attr] = config[attr]
            }
        }
        return this;
    }

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

    // 实现绑定自定义事件,不写实现系统事件
    jQuery.prototype.myOn = function(type,handle){
        for(var i = 0 ; i< this.length; i++){
            // 因为在循环中,我们需要加一个判断,判断有没有存储事件的空间: this[i].cacheEvent
            if( !this[i].cacheEvent ){
                // 如果一个dom元素上没有缓存事件,我们需要添加一个存储位置来存储所有要绑定的事件
                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 params = arguments.length > 1 ? [].slice.call(arguments,1) : [];
        var self = this;
        for( var i = 0 ; i < this.length;i++ ){
            this[i].cacheEvent[type].forEach(function(ele,index){
                ele.apply(self,params)
            })
        }
    }


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


    jQuery.prototype.queue = function(type,handle){
        // 保存this
        var queueObj = this;
        // fx是animate方法的内置队列名
        var queueName = type || 'fx';
        var addFunc = handle || null;
        // 用参数长度判断queue方法是创建队列还是查看队列
        var len = arguments.length;
        if(len == 1){
            return queueObj[0][queueName]
        }
        // 添加队列或已有的队列中添加内容
        // dom:queueObj[0]
        queueObj[0][queueName] == undefined ? queueObj[0][queueName] = [addFunc] : queueObj[0][queueName].push(addFunc)
        return this;
    }

    jQuery.prototype.dequeue = function(type){
        var self = this;
        var queueName = type || 'fx';//
        // 取出队列数组
        var queueArr = this.queue(type)//[f(1),f(2),f(3)]
        // 把数组队列汇总的第一个内容取出
        var currFunc = queueArr.shift()//f(3)
        if(currFunc == undefined){
            return;
        }
        // 但是在内容执行别忘了next技巧,造成一列穿的取出队列,递归思想
        var next = function(){
            self.dequeue(queueName)
        }
        currFunc(next)
        return this;
    }

    jQuery.prototype.delay = function(duration){
        // 把dom中的名为fx的队列
        var queueArr = this[0]['fx'];
        queueArr.push(function(next){
            setTimeout(function(){
                next()
            },duration)
        })
        return this;
    }

    jQuery.prototype.animate = function(json,duration,callback){
        var len = this.length;
        var self = this;
        // 创建一个内容函数,最后把内容函数添加到队列中,这个内容函数中肯定包含物体运动
        var baseFunc = function(next){
            // 创建一个开关,判断是否所有的物体都进行了运动 times == len
            var times = 0;
            // 利用for循环让每一个元素都添加运动方法
            for(var i = 0 ; i < len;i++){
                startMove(self[i],json,function (){
                    times ++;
                    if(times == len){
                        callback && callback()
                        next()
                    }
                })
            }
        }
        this.queue('fx',baseFunc)
        if(this.queue('fx').length == 1){
            this.dequeue('fx')
        }


        function startMove(dom, attrObj,callback) { // 传入一个元素,我让元素运动城你想要的的目标
            clearInterval(dom.timer)
            var iSpeed = null,
                iCur = null;
            dom.timer = setInterval(function () {
                var bStop = true;
                for (var attr in attrObj) { 
                    if (attr == "opacity") {
                        iCur = parseFloat(getStyle(dom, attr)) * 100
                    } else {
                        iCur = parseFloat(getStyle(dom, attr))
                    }
                    iSpeed = (attrObj[attr] - iCur) / 7;
                    iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed)
                    if (attr == "opacity") {
                        dom.style.opacity = (iCur + iSpeed) / 100
                    } else {
                        dom.style[attr] = iCur + iSpeed + "px"
                    }
                    if(iCur != attrObj[attr]){
                        bStop = false
                    }
                }
                if(bStop){
                    clearInterval(dom.timer)
                    typeof callback == "function" && callback()
                }
            }, 30)
        }
        function getStyle(dom,attr){
            if(window.getComputedStyle){
                return window.getComputedStyle(dom,null)[attr]
            }else{
                return dom.currentStyle[attr]
            }
        }
        return this;
    }
    jQuery.prototype.init.prototype = jQuery.prototype;
    // 闭包思想:函数执行完以后函数里面的变量不会被释放
    window.$ = window.jQuery = jQuery;
})()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值