原生js實現類jq框架

前言

今天來實現一個簡單的js框架,相似jq的功能,實現了增減class,增減屬性,鏈式調用,合併對象等功能,html

更加深刻理解下js原型prototype的應用,是以前承諾的原型模式應用的文章,歡迎評論交流vue

初始化方法

(function(window, document) {
    'use strict';
    // jq函數
    var myJquery = function(selector){
        return myJquery.fn.init(selector);
    }

    // 原型方法
    myJquery.fn = myJquery.prototype = {
        // 修復原型鏈
        constructor: myJquery,
        // 初始化方法
        init: function(selector) {
            if(!selector) return;
            var el = document.querySelectorAll(selector);
            el = Array.from(el);
            // 設置原型
            Object.setPrototypeOf(el,this);

            return el;
        }
    }
    // 將業務代碼註冊到全局命名空間
    window.myJquery = window.$ = myJquery;

})(window, document);

根據代碼,能夠看到首先,一個匿名自執行函數,而後在window上註冊,而後就是原型上添加init方法,這是個常規操做了;es6

設置、獲取、刪除屬性值

這裏我沒按照jq來,爲了便於理解,我分紅了三個方法設計模式

myJquery.fn = myJquery.prototype = {
            // 得到屬性
        getAttr: function(attr) {
            var i = 0,
                length = this.length;
            if(length === 0) return;

            if( length === 1){
                return this[0].getAttribute(attr);
            }
            var arr = [];
            // 遍歷
            for (; i < length; i++) {
                arr.push(this[i].getAttribute(attr));
            }
            return arr;
        },
        // 設置屬性
        setAttr: function(attr,value) {
            var i = 0,
                length = this.length;

            if( length === 0) return;

            // 單一屬性時候
            if(typeof attr === 'string' && value !== undefined){
                for (; i < length; i++) {
                    this[i].setAttribute(attr,value);
                }
            }
            // 是對象時候
            if(typeof attr === 'object'){
                for (var key in attr) {
                    if (attr.hasOwnProperty(key)) {
                        for (var j = 0; j < length; j++) {
                            this[j].setAttribute(key,attr[key]);
                        }
                    }
                }
            }

            return this;
        },
        // 刪除屬性
        removeAttr: function(attr) {
            var i = 0,
                length = this.length;
            if(length === 0) return;

            for (; i < length; i++) {
               this[i].removeAttribute(attr);
            }
            return this;
        }
}

主要仍是要判斷多種狀況,擴展自定義框架的功能,讓框架功能更增強大,我這考慮🤔了幾種狀況,不一樣的參數類型,固然可能沒有jq那麼完善了,不過看看也便於理解框架了。api

擴展方法

每一個框架都會有的,我這作了一個合併對象的功能,擴展框架的沒加,不過思路也是同樣的框架

// 合併對象
myJquery.extend = myJquery.fn.extend  = function() {
    var i = 0,
        deep = arguments[0] || {},
        _obj = {},
        length = arguments.length;
    // 淺拷貝
    if(typeof deep  === 'object'){
        [...arguments].forEach(val=>{
            if(typeof val  === 'object'){
                Object.assign(_obj,val);
            }
        });
        return _obj;
    }

    // 深拷貝
    if(typeof deep  === 'boolean'){
        [...arguments].forEach(val=>{
            if(typeof val  === 'object'){
                Object.assign(_obj,JSON.parse(JSON.stringify(val)));
            }
        });
        return _obj;
    }
}

所有代碼

下面是總體的代碼,這個簡單框架實現了添加刪除屬性,加減class,等等內容,後續,拓展代碼也是這樣加,這是對js原型模式基本應用函數

// 原生js實現框架
(function(window, document) {
    'use strict';
    // jq函數
    var myJquery = function(selector){
        return myJquery.fn.init(selector);
    }

    // 原型方法
    myJquery.fn = myJquery.prototype = {
        // 修復原型鏈
        constructor: myJquery,
        // 初始化方法
        init: function(selector) {
            if(!selector) return;
            var el = document.querySelectorAll(selector);
            el = Array.from(el);
            // 設置原型
            Object.setPrototypeOf(el,this);

            return el;
        },
        // 得到屬性
        getAttr: function(attr) {
            var i = 0,
                length = this.length;
            if(length === 0) return;

            if( length === 1){
                return this[0].getAttribute(attr);
            }
            var arr = [];
            // 遍歷
            for (; i < length; i++) {
                arr.push(this[i].getAttribute(attr));
            }
            return arr;
        },
        // 設置屬性
        setAttr: function(attr,value) {
            var i = 0,
                length = this.length;

            if( length === 0) return;

            // 單一屬性時候
            if(typeof attr === 'string' && value !== undefined){
                for (; i < length; i++) {
                    this[i].setAttribute(attr,value);
                }
            }
            // 是對象時候
            if(typeof attr === 'object'){
                for (var key in attr) {
                    if (attr.hasOwnProperty(key)) {
                        for (var j = 0; j < length; j++) {
                            this[j].setAttribute(key,attr[key]);
                        }
                    }
                }
            }

            return this;
        },
        // 刪除屬性
        removeAttr: function(attr) {
            var i = 0,
                length = this.length;
            if(length === 0) return;

            for (; i < length; i++) {
               this[i].removeAttribute(attr);
            }
            return this;
        },
        // 添加內容
        html: function(val) {
            var i = 0,
                length = this.length;
            if(length === 0 || val === undefined) return;
            for(;i<length;i++){
                this[i].innerHTML = val;
            }
            return this;
        },
        // 添加class
        addClass: function(clsName) {
            var i = 0,
                length = this.length;
            if(length === 0 || clsName === undefined) return;

            for(; i < length; i++){
                var cla = this[i].className;
                cla += " " + clsName;
                this[i].className = cla.trim();
            }
            return this;
        },
        // 刪除class
        removeClass: function(clsName) {
            var i = 0,
                length = this.length;
            if(length === 0 || clsName === undefined) return;
            var clsName = clsName.split(" ");

            for(; i<length; i++){
                var cla = this[i].className;
                cla = cla.split(" ");
                // 爲了簡潔,用了點es6代碼
                clsName.forEach(val=>{
                    cla = cla.filter(value=>value !== val);
                });
                cla = cla.join(' ').trim();
                this[i].className = cla;
            }
            return this;
        },

    }
    // 合併對象
    myJquery.extend = myJquery.fn.extend  = function() {
        var i = 0,
        deep = arguments[0] || {},
        _obj = {},
        length = arguments.length;
        // 淺拷貝
        if(typeof deep  === 'object'){
            [...arguments].forEach(val=>{
                if(typeof val  === 'object'){
                    Object.assign(_obj,val);
                }
            });
            return _obj;
        }

        // 深拷貝
        if(typeof deep  === 'boolean'){
            [...arguments].forEach(val=>{
                if(typeof val  === 'object'){
                    Object.assign(_obj,JSON.parse(JSON.stringify(val)));
                }
            });
            return _obj;
        }
    }
    // 將業務代碼註冊到全局命名空間
    window.myJquery = window.$ = myJquery;
})(window, document);

總結

js框架,都很好的運用了prototype原型,這是js開發中必需要掌握的內容,這篇文章是原型模式的應用,但願對各位看官有所啓發,this

接下來,我看看出幾篇vue的文章,再試着作個vue的簡單實現,vue的話主要運用了設計模式的觀察者模式,主要用了Object.defineProperty這個ES6的api,prototype

固然這篇文章就很少講了,但願你們看了有收穫,謝謝你們觀看😄!設計

相關文章
相關標籤/搜索