前言

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

写这个小功能的原因很简单 目前开发方式都是所有的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而已,所以也会有一些问题。