js框架封裝,模擬jQuery封裝

模擬jQuery框架,利用原生的js技術,封裝一個js框架,以加深對jQuery的經常使用api的使用和麪向對象原理的理解;
一:結構部分
首先利用閉包,構造一個自執行函數,而後利用選擇器函數Sizzle,獲取dom元素;其後設置入口函數jQuery,返回一個F的實例;
而後對jQuery.prototype進行設置;其後修改F的原型指向jQuery的原型,最後暴露出去兩個接口$和jQuery;
二:jQuery.fn.extend = jQuery.extend = function(){}
經過向jQuery的原型和jQuery上添加一個extend方法(詳見下面代碼extend部分);
能夠實現擴展工具類方法和dom操做、css操做類的方法;
jQuery.fn.extend(object); 對jQuery.fn即jQuery.prototype
得擴展,就是爲jQuery類添加「成員函數」。jQuery類的實例能夠使用這個「成員函數」。

代碼以下,歡迎指正
(function (window) {  //僞數組借用數組的push和splice方法    var arr = [];//Array.prototype;    var push = arr.push;    var splice = arr.splice;    //jQuery.extend()工具類方法中的type部分代碼預處理    var toString = Object.prototype.toString;    var types = "Number,String,Boolean,Null,Undefined,Array,Object,Function,Math,Date,RegExp".split(",");    var class2type = {};    for (var i = 0; i < types; i++) {        var type = types[i];        class2type["[object " + type + "]"] = type.toLowerCase();    }    /**     * 獲取dom元素的僞數組nodelist 不考慮兼容性問題;     * @param selector     * @returns {NodeList}     * @constructor     */    var Sizzle = function (selector) {        return document.querySelectorAll(selector);    }    /**     * 設置入口函數,返回F的實例對象     * @param selector     * @returns {*}     */    function jQuery(selector) {        return jQuery.fn.F(selector);    }    /**     * jQuery.prototype設置     * @type {{constructor: jQuery, F: Function}}     */    jQuery.fn = jQuery.prototype = {        constructor: jQuery,        version: "0.0.1",        F: function (selector) {            if (jQuery.isString(selector)) {                if (selector.charAt(0) === "<" && selector.charAt(selector.length - 1) === ">" && selector.length >= 3) {                    //eg:$("<input>");                    var div = document.createElement("div");                    div.innerHTML = selector;                    //for(var i =0;i<div.childNodes.length;i++){                    //    var child = div.childNodes[i];                    //    push.call(this.child);                    //}                    push.apply(this, div.childNodes);                } else {                    //eg:$("div")                    splice.call(this, 0, this.length);                    var elements = Sizzle(selector);                    push.apply(this, elements);                }            } else if (selector.nodeType) {                //鴨式辨型思想                //this[0] = selector;                //this.length = 1;                push.call(this, selector);            } else if (selector.version === this.version) {                return selector;            }            return this;//實現鏈式編程        }    }    /**     * extend方法     * @type {Function}     */    jQuery.fn.extend = jQuery.extend = function () {        var argLen = arguments.length;        var arg0 = arguments[0];        var sources = [];        var target;        if (argLen === 0) return this;        if (argLen === 1) {            sources.push(arg0);            target = this;        } else {            //for(var i=1;i<argLen;i++){            //    sources.push(arguments[i]);            //}            push.apply(sources, arguments);            target = arg0;        }        for (var i = 0; i < sources.length; i++) {            var source = sources[i];            for (var key in source) {                target[key] = source[key];            }        }        return target;    }    /**     * 工具類方法,添加到jQuery中,使用$.方法名()調用     */    jQuery.extend({    //判斷數據類型        type: function (data) {            return class2type[toString.call(data)];        },    //判斷是否是字符串        isString: function (str) {            return jQuery.type(str) === "string";        },    //判斷是否是函數        isFunction: function (fn) {            return jQuery.type(fn) === "function";        },     //拋出異常        error: function (msg) {            throw new Error(msg);        },     //去除字符串兩邊的空格        trim: function (str) {            return str.replace(/^\s+|\s+$/g, "");        },     //遍歷(數組的遍歷或者對象的遍歷)        each: function (array, callback) {            var len = array.length;            var i;            if (typeof len === "number" && len >= 0) {                for (i = 0; i < len;) {                    if (callback.call(array[i], i, array[i++]) === false) {                        break;                    }                }            } else {                for (i in array) {                    if (callback.call(array[i], i, array[i]) === false) {                        break;                    }                }            }        }    })    //jQuery.fn中的each方法:這樣F的實例,即jQuery的對象擁有的each方法    jQuery.fn.extend({        each: function (callback) {            jQuery.each(this, callback);            return this;        }    })    //css模塊    jQuery.fn.extend({        css: function () {            var argLen = arguments.length;            var arg0 = arguments[0];            var arg1 = arguments[1];            if (argLen === 0) return this;            if (argLen === 1) {                if (jQuery.isString(arg0)) {                    //表示獲取第一個dom元素的css樣式                    var firstDom = this[0];                    return window.getComputedStyle(firstDom, null)[arg0];                } else {                    //是一個對象的時候表示設置多個樣式                    //return this.each(function(){                    //    var dom = this;                    //    jQuery.each(arg0,function(styleName,styleValue){                    //        dom.style[styleName] = styleValue;                    //    })                    //})                    return this.each(function () {                        jQuery.extend(this.style, arg0);                    });                }            } else {                //傳遞兩個參數;設置單個css樣式                return this.each(function () {                    this.style[arg0] = arg1;                })            }        },    //顯示        show: function () {            return this.css("display", "block");        },    //隱藏        hide: function () {            return this, css("display", "none");        },    //切換顯示和隱藏        toggle: function () {            return this.each(function () {                var $this = $(this);                $this.css("display") === "none" ? $this.show() : $this.hide();            })        }    })    //屬性模塊    jQuery.fn.extend({        attr: function (arg0, arg1) {            var argLen = arguments.length;            if (argLen === 0) return this;            if (argLen === 1) {                if (jQuery.isString(arg0)) {                    //獲取第一個dom元素的屬性值                    var firstDom = this[0];                    return firstDom.getAttribute(arg0);                } else {                    //設置一個對象的屬性                    return this.each(function () {                        var dom = this;                        jQuery.each(function (className, classValue) {                            dom.setAttribute(className, classValue);                        })                    })                }            } else {                //兩個參數;設置屬性                return this.each(function () {                    this.setAttribute(arg0, arg1);                })            }        },        hasClass: function (className) {            //遍歷,只要有一個dom元素含有className這個類名就返回true            var isExist = false;            this.each(function () {                if ((" " + this.className + " ").indexOf(" " + className + " ") > -1) {                    isExist = true;                    return false;                }            })            return isExist;        },        addClass: function (className) {            var classNames = className.split(" ");            return this.each(function () {                for (var i = 0; i < classNames.length; i++) {                    var singleClassName = className[i];                    if (!$(this).hasClass(singleClassName)) {                        this.className += " " + singleClassName;                    }                }            })        },        removeClass: function (className) {            if (!className) {                //刪除所有類名                return this.each(function () {                    this.className = "";                })            } else {                //刪除一個或者多個類名                var classNames = className.split(" ");                return this.each(function () {                    var domClassName = " " + this.className + " ";                    for (var i = 0; i < classNames.length; i++) {                        var singleClassName = " " + classNames[i] + " ";                        domClassName = domClassName.replace(singleClassName, " ");                    }                    this.className = $.trim(domClassName);                })            }        }    })    //dom操做方法模塊    jQuery.fn.extend({        appendTo: function () {            var $parent = $(arguments[0]);            return this.each(function () {                var child = this;                $parent.each(function () {                    var parent = this;                    parent.appendChild(child.cloneNode(true));                })            })        },        prependTo: function () {            var $parent = $(arguments[0]);            return this.each(function () {                var child = this;                $parent.each(function () {                    var parent = this;                    parent.insertBefore(child.cloneNode(true), parent.firstChild);                })            })        },        append: function () {            var $parent = $this;            var $child = $(arguments[0]);            $child.appendTo($parent);            return this;        },        prepend: function () {            var $parent = $this;            var $child = $(arguments[0]);            $child.prependTo($parent);            return this;        },        remove: function () {            return this.each(function(){                this.parentNode.removeChild(this);            })        },        html: function (html) {            if (html === undefined) {                //返回第一個dom元素的html                var firstDom = this[0];                return firstDom.innerHTML;            }            //若是爲null或者其餘參數時候            return this.each(function () {                this.innerHTML = html;                //this.innerHTML = html===null?"":html;            })        },        text: function (text) {            if (html === undefined) {                var str = "";                this.each(function () {                    str += this.innerText;                })                return str;            }            return this.each(function () {                this.innerText = text;            })        }    })    //事件模塊    jQuery.fn.extend({        on:function(type,callback){            return this.each(function(){                this.addEventListener(type,callback);            })        }    })    var eventTypes = "click dblclivk keydown keyup mousedown mouseup mouseout mouseenter mouseleave load".split(" ");    for(var i =0;i<eventTypes.length;i++){        var eventType = eventTypes[i];        $.fn[eventType] = (function(){            var type = eventType;            return function(callback){                return this.on(type,callback);            }        })()    }    //F的實例 = jQuery的實例    jQuery.fn.F.prototype = jQuery.fn;    //暴露出去兩個接口    window.$ = window.jQuery = jQuery;})(window)
相關文章
相關標籤/搜索