InterceptorCompontent-组件注入概念

前言

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

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

1
2
3
4
5
6
7
function indexCompontent(){
console.log('index')
}
if($('js-index').length>0){
indexCompontent();
}

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

1
2
3
4
5
6
7
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或者啥变了..就获取不到了…而且这种很不直观表达..那么是否有这样一种方式 我可以动态注入比如

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

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

编写注入器

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//组件库的大概形式
allCompontents={
'.js-index':[a,b,c]
".js-login":[a,b,d]
}
//注入库的大概形式
interceptorList={
'.js-index':{
'login-arg':{
a:'123'
}
},
".js-login":{
'xx-xx':{
x:"x"
}
}
}

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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]];
}
}
}
}
}
}

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
/**
*
* @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函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
__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();
}
}
}
}
}

最终的函数形式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
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而已,所以也会有一些问题。