JS进阶系列 --- 框架封装

本文介绍了一个模仿jQuery 2.2版本自制的轻量级JavaScript库,该库提供了多种实用的DOM操作方法,如选择、操作元素及事件处理等,并对部分IE8特性进行了兼容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

作者的话

如果你和我一样是初窥前端的一个怀抱梦想的初学者,我希望我走过的这段路能对你有些许的启示,让你对前端收获一点感悟。
如果你是一个前端的大牛,也由衷的希望你能留下些许的指教。

为什么使用框架##

我们知道,原生的js虽然代码强大,可以完成几乎所有项目的开发。
但是,如果纯用原生的js来写项目,未免过于繁琐。而借助于一些js框架可以使得代码变得简练。
类比jquery和原生的id选择器:
jquery: $(’#panini’);
原生js: document.getElementById(‘panini’);
可见框架的好处了吧。
##为什么封装自己的框架##
会用框架不代表能够理解一个框架。
Jquery八千多行的代码我是无法理解的了,但是封装一个自己的框架会让你对js认识更加深入,对js的使用更加熟练。
这也是我写这个系列的初衷。

jquery1.0

这个框架是仿造jquery2.2版本做的,函数的功能也尽量向jquery靠拢。一共777行,后续还会添加新的方法。做了部分ie8的兼容。

/*******
	author by 帕尼尼  
	set time: 2018/3/29 16:27
	copy @1.00

*******/
(function( w ) {

    // jQuery工厂
    function jQuery( selector ) {
        return new App( selector );
    };
    // 这是真正的构造函数,同时把构造函数放在了原型中
    function App( selector ) {

        // null、undefined、NaN、0、false、''
        if ( !selector ) {
            return this;
        }

        // function
        if ( $.isFunction( selector ) ) {

            // 打包给ready静态方法处理
            $.ready( selector );
        }

        // string ==> ( html || selector )
        else if( $.isString( selector ) ) {

            // 为了用户友好体验,先去掉首尾空白字符
            selector = $.trim( selector );

            // html
            if( $.isHTML( selector ) ) {

                // 利用一个临时的div来创建DOM,
                // 然后把创建好的DOM依次push给实例。
                var tempDiv = document.createElement( 'div' );
                tempDiv.innerHTML = selector;
                [].push.apply( this, tempDiv.childNodes );
            }

            // selector
            else {

                try {
                    [].push.apply( this, document.querySelectorAll( selector ) );
                }catch(e) {
                    // 如果报错了,那么手动补一个length属性,代表没有获取到任何元素
                    this.length = 0;
                }
            }
        }

        // array || likeArray
        else if( $.isLikeArray( selector ) ) {
            [].push.apply( this, [].slice.call( selector ) );
        }

        // 其它
        else {
            this[0] = selector;
            this.length = 1;
        }
    };

    // 替换原型 + 原型简称
    // 替换App的原型为工厂的原型,这样外界就可以通过工厂给实例扩展方法
    App.prototype = jQuery.prototype = {
        constructor: jQuery,

        // 获取版本号
        version: "1.0.0",

        // 代表所有实例默认的选择器,也代表实例是一个jQuery类型的对象
        selector: '',

        // 代表所有实例默认的长度
        length: 0
    };

    // 给jQuery和原型分别添加extend方法
    jQuery.extend = jQuery.prototype.extend = function( obj ) {
        for ( var key in obj ) {
            this[ key ] = obj[ key ];
        }
    };

    // 暴露工厂和工厂的简称
    w.jQuery = w.$ = jQuery;

    /**
            jQuery    
    ***/

    // 给jQuery添加一些静态方法(兼容ie8)
    $.extend({

        //获取样式
        getStyle: function(dom,style){
            if(window.getComputedStyle){
                return window.getComputedStyle(dom)[style];
            }else{//ie8
                return dom.currentStyle[style];
            }
        },

        // 去掉首尾空白字符
        trim: function( str ) {
            return str.trim ? str.trim() : str.replace( /^\s+|\s+$/g, '');
        },
    });

    // 给jQuery添加一些静态方法(is)
    $.extend({

        // 判断是不是html片段
        isHTML: function( html ) {

            // <.>
            if( html.charAt(0) === '<' &&
                    html.charAt( html.length - 1 ) === '>' &&
                    html.length >= 3 ) {
                return true;
            }

            return false;
        },

        // 判断是不是函数
        isFunction: function( fn ) {

            return typeof fn === 'function';
        },

        // 判断是不是window
        isWindow: function( w ) {

            return  w.window === w;
        },

        // 判断是不是对象
        isObject: function( obj ) {

            // 如果是object或function,那就是对象
            if ( typeof obj === 'object' || typeof obj === 'function' ) {
                return true;
            }

            return false;
        },

        // 判断是不是字符串
        isString: function( str ) {

            return typeof str === 'string';
        },


        // 判断是不是真数组或伪数组
        isLikeArray: function( arr ) {

            // Function、window、!Object
            if ( $.isFunction( arr ) || $.isWindow( arr ) || !$.isObject( arr ) ) {
                return false;
            }

            // 判断是不是真数组
            if ( ({}).toString.call( arr ) === '[object Array]' ) {
                return true;
            }

            // 判断是不是伪数组
            if ( 'length' in arr && ( arr.length === 0 || arr.length - 1 in arr ) ) {
                return true;
            }

            return false;
        }
    });

    // 给jQuery添加一些静态方法
    $.extend({

        ready: function( fn ) {

            // 先统一判断DOMContentloaded有没有触发,
            // 通过document.readyState === 'complete'判断
            // 如果为true,fn可以直接调用。

            // 如果为false,那么判断支不支持addEventListener,
            // 如果支持,绑定DOMContentLoaded事件

            // 如果不支持,使用attchEvent绑定onreadystatechang事件,
            // 注意,需要在里面判断document.readyState === 'complete'才执行fn。
            // 防止fn多次执行。

            // DOM已经构造完毕,fn可以直接执行
            if ( document.readyState === 'complete' ) {
                fn();
            }

            // 如果DOM没有构造完毕,那么判断addEventListener是否兼容
            else if( document.addEventListener ) {
                document.addEventListener( 'DOMContentLoaded', fn );
            }

            // 如果不兼容addEventListener,那么采取attachEvent的方式,
            // 同时事件变为了onreadystatechange,为了防止这个事件多次触发造成的fn多次执行,
            // 所以需要一个包装函数来进行过滤。
            else {
                document.attachEvent( 'onreadystatechange', function() {
                    if( document.readyState === 'complete' ) {
                        fn();
                    }
                } );
            }
        },

        //遍历每一个元素
        each: function(obj,fn){
            if($.isLikeArray(obj)){
                for(let i=0;i<obj.length;i++){
                    if(fn.call(obj[i],i,obj[i]) === false){
                        break;
                    }
                }
            }else{
                for(let key in obj){
                    if(fn.call(obj[key],key,obj[key]) === false){
                        break;
                    }
                }
            }
            return obj;
        },

        //遍历每一个元素,返回新数组
        map: function(obj,fn){
            let arr = [];
            if($.isLikeArray(obj)){
                for(let i=0;i<obj.length;i++){
                    arr.push(fn.call(obj[i],obj[i],i));
                }
            }else{
                for(let key in obj){
                    arr.push(fn.call(obj[key],obj[key],key));
                }
            }
            return arr;
        }
    });

    // 给jQuery添加事件方法
    $.extend({

        //添加一个事件
        addEvent: function(dom,type,fn){
            if(dom.addEventListener)
                dom.addEventListener(type,fn);
            else
                dom.attachEvent('on'+type,fn);
        },

        //删除一个事件
        removeEvent: function(dom,type,fn){
            if(dom.removeEventListener)
                dom.removeEventListener(type,fn);
            else
                dom.detachEvent('on'+type, fn);
        } 
    });

     // 给jQuery添加Ajax方法
     $.extend({
        ajax: function(data){
            //第一步:创建xhr对象
            var xhr = null;
            if(window.XMLHttpRequest)
                xhr = new XMLHttpRequest();
            else
                xhr = new ActiveXObject("Microsoft.XMLHTTP");
            //第二步:准备发送前的一些配置参数
            xhr.open(data.type,data.url,true);
            //第三步:执行发送的动作
            if(data.type == 'get'){
                    xhr.send(null);
            }else if(data.type == 'post'){
                    xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
                    xhr.send(data.data);
            }
            //第四步:指定回调函数
            xhr.onreadystatechange = function(){
                if(xhr.readyState == 4 ){
                    if(xhr.status == 200)//执行成功
                        data.success(xhr.responseText);
                    else
                        data.failure();
                }
            }
        }
     });


    /**
            jQuery实例    
    ***/

    // 给jQuery实例添加元素操作方法
    $.prototype.extend({
        // 把实例(伪数组)转换为数组返回 
        toArray: function() {
            return [].slice.call( this );
        },

        // 获取指定下标的元素,获取的是原生DOM
        get: function( i ) {
            /*
            * 1、如果传入null或undefined,那么转换为数组返回
            * 2、如果传入的是正数,按照指定的下标获取元素返回
            * 3、如果传入的是负数,按照下标倒着( this.length + 负数 )获取元素返回
            * */
            // null、undeinfed
            if ( i == null ) {
                return this.toArray();
            }

            // 其他
            if ( i >= 0 ) {
                return this[ i ];
            }else {
                return this[ this.length + i ];
            }
        },

        // 截取实例的部分元素,构成一个新的jQuery实例返回
        slice: function() {
            /*
            * 1、通过数组的slice截取部分元素(slice返回的是数组),
            * 2、把截取到的元素转换为实例对象返回。
            * */

            // 因为slice的参数会有变化,所以需要是arguments,
            // 我们要把arguments中的每一项传给数组的slice,所以需要借用apply平铺传递过去,
            // 最后把slice返回数组,通过jQuery工厂保证成实例返回。
            return $( [].slice.apply( this, arguments ) );
        },

        // 获取指定下标的元素,获取的是jQuery类型的实例对象。
        eq: function( i ) {
            /*
             * 1、如果传入null或undefined,返回一个新实例,
             * 2、如果传入的是正数,按照指定的下标获取元素,再包装成新实例返回
             * 3、如果传入的是负数,按照下标倒着( this.length + 负数 )获取元素,再包装成新实例返回
             * */

            // null、undefined得到新实例
           return i == null? $() : $( this.get( i ) );
        },

        // 获取实例中的第一个元素,是jQuery类型的实例对象。
        first: function() {
            return this.eq( 0 );
        },

        // 获取实例中的最后一个元素,是jQuery类型的实例对象。
        last: function() {
            return this.eq( -1 );
        },

        //清空所有元素的内容
        empty: function(){
            this.each(function(){
                this.innerHTML = "";
            });
            return this;
        },

        //删除所有元素
        remove: function(){
            this.each(function(){
                this.parentNode.removeChild(this);
            });
            return this;
        },

        //获取第一个元素的内容;设置所有元素的内容
        html: function(ctx){
            //获取第一个元素的内容
            if(arguments.length === 0){
                return this[0].innerHTML;   
            }
            //设置所有元素的内容
            this.each(function(){
                this.innerHTML = ctx;
            });
            return this;
        },

        //获取所有元素的文本内容;设置所有元素的文本内容
        text: function(ctx){
            //获取所有元素的文本内容
            if(!ctx){
                return this[0].innerText;   
            }
            //设置所有元素的文本内容
            this.each(function(){
                this.innerText = ctx;
            });
            return this;
        },

        //遍历实例中的每一个元素
        each: function(fn){
            for(let i=0;i<this.length;i++){
                if(fn.call(this[i],i,this[i]) === false){
                    break;
                }
            }
            return this;
        },

        //遍历每一个元素,返回新数组
        map: function(fn) {
            let arr = [];
            for(let i=0;i<this.length;i++){
                arr.push(fn.call(this[i],this[i],i));
            }
            return arr;
        },  

        // 原型上的方法供实例调用,
        // 即实例.push,在调用过程中,push内的this就指向了实例,
        // 所以这里不需要通过call和apply改变this指向即可借用数组的方法
        push: [].push,
        sort: [].sort,
        splice: [].splice
    });

    // 给jQuery实例添加Dom方法
    $.prototype.extend({

        __operDom: function(selector,fn){
            let self = this;
            selector.each(function(){
                let dom = this;
                self.each(function(key){
                    if(key !== 0)
                        dom = dom.cloneNode(true);
                    fn.call(this,dom);
                });
            });
        },

        //把B加到A内的最后
        append: function(selector){
            this.__operDom($(selector),function(dom){
                this.appendChild(dom);
            });
            return this;
        },

        //把B加到A内的最前
        prepend: function(selector){
            this.__operDom($(selector),function(dom){
                this.insertBefore(dom,this.firstChild);
            });
            return this;
        },

        //把A加到B内的最后
        appendTo: function(selector){
            this.__operDom.call($(selector),this,function(dom){
                this.appendChild(dom);
            });
            return this;
        },

        //把A加到B内的最前
        prependTo: function(selector){
            this.__operDom.call($(selector),this,function(dom){
                this.insertBefore(dom,this.firstChild);
            });
            return this;
        },

        //把B加到A外的前面
        before: function(selector){
            this.__operDom($(selector),function(dom){
                this.parentNode.insertBefore(dom,this);
            });
            return this;
        },

        //把B加到A外的后面
        after: function(selector){
            this.__operDom($(selector),function(dom){
                this.parentNode.insertBefore(dom,this.nextSibling);
            });
            return this;
        },

        __append: function(selector){
            selector = $(selector);
            let self = this;
            selector.each(function(){
                let dom = this;
                self.each(function(key){
                    if(key !== 0)
                        dom = dom.cloneNode(true);
                    this.appendChild(dom);
                });
            });
            
        },

        __prepend: function(selector){
            selector = $(selector);
            let self = this;
            selector.each(function(){
                let dom = this;
                self.each(function(key){
                    if(key !== 0)
                        dom = dom.cloneNode(true);
                    this.insertBefore(dom,this.firstChild);
                });
            });
        },

        __appendTo: function(selector){
           selector = $(selector);
           let self = this;
           this.each(function(){
                let dom = this;
                selector.each(function(key){
                    if(key !== 0)
                        dom = dom.cloneNode(true);
                    this.appendChild(dom);
                });
           });
        },

        __prependTo: function(selector){
            selector = $(selector);
            this.each(function(){
                 let dom = this;
                 selector.each(function(key){
                     if(key !== 0)
                         dom = dom.cloneNode(true);
                     this.insertBefore(dom,this.firstChild);
                 });
            });
        },

        __before: function(selector){
            selector = $(selector); //要插入的内容
            let self = this;
            selector.each(function(){
                let dom = this;
                self.each(function(key){
                    if(key !== 0)
                        dom = dom.cloneNode(true);
                    this.parentNode.insertBefore(dom,this);
                });
            });
        },

        __after: function(selector){
            selector = $(selector); //要插入的内容
            let self = this;
            selector.each(function(){
                let dom = this;
                self.each(function(key){
                    if(key !== 0)
                        dom = dom.cloneNode(true);
                    this.parentNode.insertBefore(dom,this.nextSibling);
                });
            });
        }
    });
    
    // 给jQuery实例添加Class方法
    $.prototype.extend({

        __add: function(className){
            this.each(function(){
                this.className += ' ' + className; 
            });
        },

        __remove: function(className){
            this.each(function(){
                this.className = (' ' + this.className + ' ')
                .replace(' ' + className + ' ',' ');
            });
        },

        //操作class
        __operClass: function(className,action){
            if($.isString(className))
                className = $.trim(className).split(" ");
            let self;
            this.each(function(){
                self = this;
                $.each(className,function(){
                    self.classList[action](this);
                });
            });
            return this;
        },

        //给所有元素添加新的class
        addClass: function(className){
            if(arguments.length === 0)
                return this;
            return this.__operClass(className,"add");
        },

        //删除所有元素指定的class
        removeClass: function(className){
            if(arguments.length === 0){
                this.each(function(){
                    this.className = "";
                });
                return this;
            }
            return this.__operClass(className,"remove");
        },

        //有则删除,没有则添加
        toggleClass: function(className){
            if(arguments.length === 0)
                return this;
            return this.__operClass(className,"toggle");
        }, 

        //判断元素有没有指定的class(只要有一个)
        hasClass: function(className){
            let flag = false;
            if(arguments.length === 0)
                return flag;
            this.each(function(){
                if(this.classList.contains(className)){
                    flag = true;
                    return;
                }
            });
            return flag;
        }
    });

    // 给jQuery实例添加属性方法
    $.prototype.extend({
        //获取或者设置属性节点
        attr: function(attrName,attrVal){
            if(!$.isString(attrName) && !$.isObject(attrName))
                return this;
            if($.isString(attrName)){
                if(arguments.length === 1)
                    return this[0].getAttribute(attrName);
                else{
                    this.each(function(){
                        this.setAttribute(attrName, attrVal);
                    });
                    return this;
                }
            }else{
                for(attr in attrName){
                    this.each(function(){
                        this.setAttribute(attr, attrName[attr]);
                    });
                }
                return this;
            }
        },

        //获取或者设置属性
        prop: function(propName,propVal){
            if(!$.isString(propName) && !$.isObject(propName))
                return this;
            if($.isString(propName)){
                if(arguments.length === 1)
                    return this[0][propName];
                else{
                    this.each(function(){
                        this[propName] = propVal;
                    });
                    return this;
                }
            }else{
                for(prop in propName){
                    this.each(function(){
                        this[prop] = propName[prop];
                    });
                }
                return this;
            }
        },

        //获取或者设置value
        val: function(val){
            if(arguments.length === 0)
                return this[0].value;
            else {
                this.each(function(){
                    this.value = val;
                });
                return this;
            }
        },

        //获取或者设置样式
        css: function(cssName,cssVal){
            if(!$.isString(cssName) && !$.isObject(cssName))
                return this;
            if($.isString(cssName)){
                if(arguments.length === 1){
                    return $.getStyle(this[0],cssName);
                }
                else{
                    this.each(function(){
                        this.style[cssName] = cssVal;
                    });
                    return this;
                }
            }else{
                for(css in cssName){
                    this.each(function(){
                        this.style[css] = attrName[css];
                    });
                }
                return this;
            }
        },

        //获取或者设置自定义属性
        data: function(dataName,dataVal){
            if(arguments.length === 0)
                return this[0].dataset;
            else if(arguments.length === 1){
                return this[0].dataset[dataName];
            }else{
                this[0].dataset[dataName] = dataVal;
                return this;
            }
        }
    });

    // 给jQuery实例添加事件方法
    $.prototype.extend({

        //添加一个事件
        on: function(type,fn){
            this.each(function(){
                $.addEvent(this,type,fn);
            });
            return this;
        },
        
        //删除一个事件
        off: function(type,fn){
            this.each(function(){
                $.removeEvent(this,type,fn);
            });
            return this;
        }
    });

}( window ));

jquery2.0

这里用了class语法重写了框架,没有做兼容处理,没有做选择器

/*******
	author by 帕尼尼  
	set time: 2018/3/29 16:27
	copy @1.00

*******/
class JQuery {
    /**
     * 构造函数
     * @param   {string}  selector  选择器字符串
     * @param   {dom}   selector    dom对象
     * @return   {jquery}   jquery对象
     */
    constructor(selector) {
        if(Tool.isString(selector)) {
            [].push.apply(this, document.querySelectorAll(selector));
        } else {
            [].push.call(this, selector);
        }
    }
    /**
     * 获取第index个jquery对象
     * @param   {number}  index  位置
     * @return   {jquery}   jquery对象
     */
    eq(index) {
        return $(this[index]); 
    }
    /**
     * 获取第index个dom对象
     * @param   {number}  index  位置
     * @return   {dom}   dom对象
     */
    get(index) {
        return this[index];
    }
    /**
     * 获取第一个dom对象
     * @param   {void}
     * @return   {dom}   dom对象
     */
    first() {
        return this[0];
    }
    /**
     * 获取最后一个dom对象
     * @param   {void}
     * @return   {dom}   dom对象
     */
    last() {
        return this[this.length-1];
    }
    /**
     * 遍历jquery对象
     * @param   {function}  fn  回调函数
     * @return   {jquery}   jquery对象
     */
    each(fn) {
        for(let i=0; i<this.length; i++) {
            fn.call(this[i],i);
        }
        return this;
    }
    /**
     * 遍历操作jquery对象
     * @param   {function}  fn  回调函数
     * @return   {array}   数组
     */
    map(fn) {
        let arr = [];
        for(let i=0; i<this.length; i++) {
            arr.push(fn.call(this[i]));
        }
        return arr;
    }
    /**
     * 设置jquery对象html值/获取第一个dom对象html值
     * @param   {string}    ctx 内容
     * @return   {string} 第一个dom对象html值
     * @return   {jquery}   jquery对象
     */
    html(ctx) {
        if(!ctx) {
            return this.first().innerHTML;
        }
        this.each(function(){
            this.innerHTML = ctx;
        });
        return this;
    }
    /**
     * 设置jquery对象text值/获取第一个dom对象text值
     * @param   {string}    ctx 内容
     * @return   {string} 第一个dom对象text值
     * @return   {jquery}   jquery对象
     */
    text(ctx) {
        if(!ctx) {
            return this.first().innerText;
        }
        this.each(function(){
            this.innerText = ctx;
        });
    }
    /**
     * 为jquery对象操作类
     * @param   {array}    classNames 类数组
     * @param   {string}    action 操作方法
     */
    __operClass(classNames, action) {
        if(Tool.isString(classNames)) {
            classNames = classNames.split(' ');
        }
        this.each(function(){
            for(let className of classNames) {
                this.classList[action](className);
            }
        });
    }
    /**
     * 添加类
     * @param   {array}    classNames 类数组
     * @return   {void}
     */
    addClass(classNames) {
        if(!Tool.isNoParam(arguments)) {
            this.__operClass(classNames, 'add');
        }
        return this;
        
    }
    /**
     * 删除类
     * @param   {array}    classNames 类数组
     * @return   {void}
     */
    removeClass(classNames) {
        if(Tool.isNoParam(arguments)) {
            return this.emptyClass();
        }
        this.__operClass(classNames, 'remove');
        return this;
    }
    /**
     * 转换类
     * @param   {array}    classNames 类数组
     * @return   {void}
     */
    toggleClass(classNames) {
        if(!Tool.isNoParam(arguments)) {
            this.__operClass(classNames, 'toggle');
        }
        return this;
    }
    /**
     * 判断类
     * @param   {array}    className 类名
     * @return   {boolean}
     */
    hasClass(className) {
        let flag = false;
        if(Tool.isNoParam(arguments))
            return flag;
        this.each(function(){
            if(this.classList.contains(className)){
                flag = true;
                return false;
            }
        });
        return flag;
    }
    /**
     * 清空类
     * @param   {array}    className 类名
     * @return   {jquery}   jquery对象
     */
    emptyClass() {
        this.each(function(){
            this.classList = '';
        });
        return this;
    }
    /**
     * 获取/设置属性
     * @param   {string/object}    attrName 属性名/属性对象
     * @param   {string}    attrVal 属性值
     * @return   {jquery}   jquery对象
     */
    attr(attrName, attrVal) {
        if(!Tool.isStringOrObject(attrName)) {
            return this[0].attributes;
        }
        if(Tool.isString(attrName)) {
            if(Tool.isSingleParam(arguments)) {
                return this[0].getAttribute(attrName);
            } else {
                if(!attrVal) {
                    this.each(function(){
                        this.removeAttribute(attrName);
                    });
                } else {
                    this.each(function(){
                        this.setAttribute(attrName, attrVal);
                    });
                }
            }
        } else {
            for(let attr in attrName) {
                this.each(function(){
                    this.setAttribute(attr, attrName[attr]);
                });
            }
        }
        return this;
    }
    /**
     * 获取/设置值
     * @param   {string}    val 值
     * @return   {string}    属性值
     * @return   {jquery}   jquery对象
     */
    val(val) {
        if(Tool.isNoParam(arguments)) {
            return this[0].value;
        } else {
            this.each(function(){
                this.value = val;
            });
        }
        return this;
    }
    /**
     * 获取/设置css
     * @param   {string/object}    cssName css名
     * @param   {string}    cssValue css值
     * @return   {jquery}   jquery对象
     */
    css(cssName, cssValue) {
        if(!Tool.isStringOrObject(cssName)) {
            return this[0].style;
        } else if (Tool.isString(cssName)) {
            if(Tool.isSingleParam(arguments)) {
                return window.getComputedStyle(this[0])[cssName];
            } else {
                this.each(function(){
                    this.style[cssName] = cssValue;
                });
            }
        } else {
            for(let css in cssName) {
                this.each(function(){
                    this.style[css] = cssName[css];
                });
            }
        }
        return this;
    }
    /**
     * 获取/设置自定义属性
     * @param   {string/object}    cssName css名
     * @param   {string}    cssValue css值
     * @return   {jquery}   jquery对象
     */
    data(dataName,dataVal) {
        if(!Tool.isStringOrObject(dataName)) {
            return this[0].dataset;
        } else if(Tool.isString(dataName)) {
            if(Tool.isSingleParam(arguments)) {
                return this[0].dataset[dataName];
            } else {
                this.each(function(){
                    this.dataset[dataName] = dataVal;
                });
            }
        } else {
            for(let data in dataName) {
                this.each(function(){
                    this.dataName[data] = dataName[data];
                });
            }
        }
    }

    __operDom(dom,fn) {
        this.each(function(index){
            if(index !== 0) {
                dom = dom.cloneNode(true);
            }
            fn.call(this, dom);
        });
        return this;
    }
    //把B加到A内的最后
    append(dom) {
        return this.__operDom(dom,function(dom){
            this.appendChild(dom);
        });
    }
    //把A加到B内的最后
    appendTo(dom) {
        return this.__operDom(dom,function(dom){
            dom.appendChild(this);
        });
    }
    //把B加到A内的最前
    prepend(dom) {
        return this.__operDom(dom,function(dom){
            this.insertBefore(dom, this.firstChild);
        });
    }
    //把A加到B内的最前
    prependTo(dom) {
        return this.__operDom(dom,function(dom){
            dom.insertBefore(this, dom.firstChild);
        });
    }
    //把B加到A外的前面
    before(dom) {
        return this.__operDom(dom, function(dom){
            this.parentNode.insertBefore(dom, this);
        });
    }
    //把B加到A外的后面
    after(dom) {
        return this.__operDom(dom, function(dom){
            this.parentNode.insertBefore(dom, this.nextSibling);
        });
    }
    /**
     * 删除jquery对象
     * @param   {void}
     * @return   {void}
     */
    remove() {
        this.parentNode.removeChild(this);
    }
    /**
     * 清空jquery对象
     * @param   {void}
     * @return   {jquery}   jquery对象
     */
    empty() {
        this.each(function(){
            this.innerHTML = '';
        });
        return this;
    }
    hide() {
        this.css('display','none');
    }
    show() {
        this.css('display','');
    }
    toggle() {
        this.each(function(){
            let $this = $(this);
            $this.css('display') === 'none' ? $this.show() : $this.hide();
        });
    }
}

const Tool = {
    /**
    * 判断是否为string
    * @param   {unknown}  string
    * @return   {boolean}
    */
    isString: function(string) {
        return typeof string === 'string';
    },
    /**
    * 判断是否为object
    * @param   {unknown}  object
    * @return   {boolean}
    */
    isObject: function(object) {
        if ( typeof object === 'object' || typeof object === 'function' ) {
            return true;
        }
        return false;
    },
    /**
    * 判断是否为string或者为object
    * @param   {unknown}  obj
    * @return   {boolean}
    */
    isStringOrObject: function(obj) {
        return  Tool.isString(obj) || Tool.isObject(obj); 
    },
    /**
    * 判断参数个数是否为0
    * @param   {arguments}  参数数组
    * @return   {boolean}
    */
    isNoParam: function(arguments) {
        return arguments.length === 0;
    },
    /**
    * 判断参数个数是否为1
    * @param   {arguments}  参数数组
    * @return   {boolean}
    */
    isSingleParam: function(arguments) {
        return arguments.length === 1;
    }
}

window.$ = function(selector) {
    return new JQuery(selector);
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值