InterceptorCompontent-组件注入概念

191 阅读3分钟
原文链接: emufan.com

前言

本来想定义为拦截器概念的…后来想想好像不对..应该是注入器概念..不过组件名都写好了 就懒得改了.

写这个小功能的原因很简单 目前开发方式都是所有的js放一个文件里了,那么如果我有多个页面,每个页面执行不同的函数 实现方式是不是很简单?

function indexCompontent(){
    console.log('index')
}
if($('js-index').length>0){
    indexCompontent();
}

用es6的语法写起来就更爽了,可以把每个函数拆开,但是如果我后台想传递一些参数…那是不是很蛋疼了,估计要绑定在html上 然后通过函数主动去获取..

div.js-index(data-user='{"name":"soul","uid":"2333"}')
script.
    function indexCompontent(){
        let s=$('.js-index').attr('data-user');
        let data=JSON.parse(s);
    }

这样写就有点蛋疼了..因为我需要主动的去获取html上的元素..一旦html元素id或者啥变了..就获取不到了…而且这种很不直观表达..那么是否有这样一种方式 我可以动态注入比如

window.startApp.addInterceptor('login-arg',".js-index",{a:"123"});

login-arg为自定义的参数辨识号,第二个为需要注入的组件名字,最后一个参数为传递的数据

编写注入器

因为这里依赖了Jquery,所以需要传递进入jQuery,为了兼容原有的组件,那么肯定是需要做一个转换的,这里的思路也比较简单 用两个对象来保存组件库和注入库

//组件库的大概形式
allCompontents={
    '.js-index':[a,b,c]
    ".js-login":[a,b,d]
}
//注入库的大概形式
interceptorList={
    '.js-index':{
        'login-arg':{
            a:'123'
        }
    },
    ".js-login":{
        'xx-xx':{
            x:"x"
        }
    }
}

首先为做适配器,把原有的组件列表转为新的组件列表..因为原有的可能就是一个组件对应一个函数,而新有的是一个组件对应多个函数

class InterceptorCompontent{
    /**
     *
     * @param $                 jQuery
     * @param allCompontents    原有组件列表
     */
    constructor($,allCompontents={}){
        this.allCompontents=allCompontents;
        this.$=$;
        this.interceptorList={};
        //转换单个func为array
        if(this.allCompontents){
            for (let item of Object.keys(this.allCompontents)){
                if(item){
                    if(!this.$.isArray(this.allCompontents[item])){
                        this.allCompontents[item]=[this.allCompontents[item]];
                    }
                }
            }
        }
    }
}

编写填写组件和拦截器函数

这里也就是核心的函数了,不过根据上述的组件库和注入库列表来看应该就比较好理解了

/**
 *
 * @param obj           需要添加数据的对象
 * @param name          数据的key
 * @param data          数据的data
 * @param customName    是否以对象的形式来添加组件
 * @private
 */
__addFunc(obj,name,data,customName){
    let current=obj[name];
    //是否存在当前有对应的component
    if(current){
        if(!customName){
            //数组的形式添加
            if(!this.$.isArray(current)) {
                //当前对应的component函数不为数组
                obj[name] = [current];
                //添加新的component执行函数
                obj[name].push(data);
            }else if(this.$.isArray(current)){
                //当前对应的component函数为数组
                obj[name].push(data);
            }
        }else{
            //对象的形式添加
            if(!this.$.isArray(current)&&typeof current =='object') {
                //当前对应的component函数为对象
                if(obj[name][customName]){
                    //如果已经存在当前自定义名称则扩展对象
                    Object.assign(obj[name][customName],data);
                }else{
                    obj[name] ={
                        [customName]:data
                    };
                }
            }else if(this.$.isArray(current)){
                //当前对应的component函数为数组
                obj[name].push(data);
            }
        }
    }else{
        if(!customName){
            //不存在对应的component
            obj[name] = [];
            //添加新的component执行函数
            obj[name].push(data);
        }else{
            obj[name] ={
                [customName]:data
            };
        }
    }
}
/**
 *
 * @param name  组件名
 * @param func  组件执行函数
 */
addCompontents(name,func){
    this.__addFunc(this.allCompontents,name,func);
}
/**
 * 添加拦截器
 * @param   {String}  customName    自定义名
 * @param   {String}  key           组件名
 * @param   {Object}  data          必须为对象
 *
 */
addInterceptor(customName,key,data){
    if(!customName||!key||!data){
        throw new Error(`必须传递 customName,key,data`);
        return false;
    }
    this.__addFunc(this.interceptorList,key,data,customName);
}

编写init函数

__isExistCompontent(elem){
        return this.$(elem).length>0?true:false;
}
    
init(){
        for(let item of Object.keys(this.allCompontents)){
            if(this.__isExistCompontent(`${item}`)){
                //alert(`执行:${item}`,)
                for(let func of this.allCompontents[item]){
                    //是否存在注入器
                    if(this.interceptorList[item]){
                        func(this.interceptorList[item]);
                    }else{
                        func();
                    }
                }
            }
        }
    }

最终的函数形式


export default class InterceptorCompontent{
    /**
     *
     * @param $                 jQuery
     * @param allCompontents    原有组件列表
     */
    constructor($,allCompontents={}){
        this.allCompontents=allCompontents;
        this.$=$;
        this.interceptorList={};
        //转换单个func为array
        if(this.allCompontents){
            for (let item of Object.keys(this.allCompontents)){
                if(item){
                    if(!this.$.isArray(this.allCompontents[item])){
                        this.allCompontents[item]=[this.allCompontents[item]];
                    }
                }
            }
        }
    }
    
    __isExistCompontent(elem){
        return this.$(elem).length>0?true:false;
    }
    /**
     *
     * @param obj           需要添加数据的对象
     * @param name          数据的key
     * @param data          数据的data
     * @param customName    是否以对象的形式来添加组件
     * @private
     */
    __addFunc(obj,name,data,customName){
        let current=obj[name];
        //是否存在当前有对应的component
        if(current){
            if(!customName){
                //数组的形式添加
                if(!this.$.isArray(current)) {
                    //当前对应的component函数不为数组
                    obj[name] = [current];
                    //添加新的component执行函数
                    obj[name].push(data);
                }else if(this.$.isArray(current)){
                    //当前对应的component函数为数组
                    obj[name].push(data);
                }
            }else{
                //对象的形式添加
                if(!this.$.isArray(current)&&typeof current =='object') {
                    //当前对应的component函数为对象
                    if(obj[name][customName]){
                        //如果已经存在当前自定义名称则扩展对象
                        Object.assign(obj[name][customName],data);
                    }else{
                        obj[name] ={
                            [customName]:data
                        };
                    }
                }else if(this.$.isArray(current)){
                    //当前对应的component函数为数组
                    obj[name].push(data);
                }
            }
        }else{
            if(!customName){
                //不存在对应的component
                obj[name] = [];
                //添加新的component执行函数
                obj[name].push(data);
            }else{
                obj[name] ={
                    [customName]:data
                };
            }
        }
    }
    /**
     *
     * @param name  组件名
     * @param func  组件执行函数
     */
    addCompontents(name,func){
        this.__addFunc(this.allCompontents,name,func);
    }
    /**
     * 添加拦截器
     * @param   {String}  customName    自定义名
     * @param   {String}  key           组件名
     * @param   {Object}  data          必须为对象
     *
     */
    addInterceptor(customName,key,data){
        if(!customName||!key||!data){
            throw new Error(`必须传递 customName,key,data`);
            return false;
        }
        this.__addFunc(this.interceptorList,key,data,customName);
    }
    init(){
        for(let item of Object.keys(this.allCompontents)){
            if(this.__isExistCompontent(`${item}`)){
                //alert(`执行:${item}`,)
                for(let func of this.allCompontents[item]){
                    //是否存在注入器
                    if(this.interceptorList[item]){
                        func(this.interceptorList[item]);
                    }else{
                        func();
                    }
                }
            }
        }
    }
}
执行的话也比较简单 
script.
     window.startApp=new InterceptorCompontent($,allCompontents);
     window.startApp.addInterceptor('login-arg',".js-login",{a:"123"});
     window.startApp.init();//必须放到最后执行

不足

这个函数日常来用应该是没有什么问题了,但是如果出现了注入参数名相同的问题,那么这个是覆盖还是提示报错就有待讨论了.
添加组件的时候 如果传递的是一个数组,那么这里并没有做数组扁平化处理 仅仅是直接push而已,所以也会有一些问题。