原生js实现类jq框架

yuanfa247

前言

今天来实现一个简单的js框架,类似jq的功能,实现了增减class,增减属性,链式调用,合并对象等功能,

更加深入理解下js原型prototype的应用,是之前承诺的原型模式应用的文章,欢迎评论交流

初始化方法

(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方法,这是个常规操作了;

设置、获取、删除属性值

这里我没按照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那么完善了,不过看看也便于理解框架了。

扩展方法

每个框架都会有的,我这做了一个合并对象的功能,扩展框架的没加,不过思路也是一样的

// 合并对象
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开发中必须要掌握的内容,这篇文章是原型模式的应用,希望对各位看官有所启发,

接下来,我看看出几篇vue的文章,再试着做个vue的简单实现,vue的话主要运用了设计模式的观察者模式,主要用了Object.defineProperty这个ES6的api,

当然这篇文章就不多讲了,希望大家看了有收获,谢谢大家观看?!

阅读 1.1k
21 声望
0 粉丝
0 条评论
21 声望
0 粉丝
文章目录
宣传栏