组件化封装
JS组件封装

基本方法(以轮播图组件为例)
- 结构设计
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16<div id="my-slider" class="slider-list">
<ul>
<li class="slider-list__item--selected">
<img src="xx.png"/>
</li>
<li class="slider-list__item">
<img src=""/>
</li>
<li class="slider-list__item">
<img src=" "/>
</li>
<li class="slider-list__item">
<img src=""/>
</li>
</ul>
</div> - 展现效果
- 行为设计
- API(功能)
- Event(控制流)但是这样功能虽然实现,但是
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
36class Slider{
constructor(id){
this.container = document.getElementById(id);
this.items = this.container
.querySelectorAll('.slider-list__item, .slider-list__item--selected');
}
getSelectedItem(){
const selected = this.container
.querySelector('.slider-list__item--selected');
return selected
}
getSelectedItemIndex(){
return Array.from(this.items).indexOf(this.getSelectedItem());
}
slideTo(idx){
const selected = this.getSelectedItem();
if(selected){
selected.className = 'slider-list__item';
}
const item = this.items[idx];
if(item){
item.className = 'slider-list__item--selected';
}
}
slideNext(){
const currentIdx = this.getSelectedItemIndex();
const nextIdx = (currentIdx + 1) % this.items.length;
this.slideTo(nextIdx);
}
slidePrevious(){
const currentIdx = this.getSelectedItemIndex();
const previousIdx = (this.items.length + currentIdx - 1)
% this.items.length;
this.slideTo(previousIdx);
}
}
- 可扩展性差,例如假如要加导航栏,既要改js,还要对应加上html和css
- 可复用性差,多次使用该组件需要多次复制相同的代码
如何改进?
重构
插件化
解耦
- 将控制元素抽取成插件
1
2
3registerPlugins(...plugins){
//abstract
}; - 插件与组件通过依赖注入方式建立联系通过把组件的组成部分抽象成插件,我们只要在使用该组件时传入要注册的插件,就可以方便的实现组件的增删,并且后来如果还要编写新的插件也可以按原逻辑在原有js上增加。
1
2
3
4
5
6
7
8
9const pluginController = {
//abstract
action(slider){
//abstraction
}
}
const pluginPrevious = {
//abstract
}模板化
- 将HTML模板化。更易于扩展
在插件的render方法中把组件的html模板化,此时,组件的html代码只有短短一行1
2
3render(){
return `<a class="slide-list__previous"></a>`;
},1
<div id="my-slider" class="slider-list"></div>
抽象化(组件框架)
- 将组件通用模型抽象出来这里把通用的组件模型抽象为一个Component类,后来增添新组件可通过
1
2
3
4
5
6
7
8
9
10
11
12
13
14class Component {
constructor(id, opts = { name, data: [] }) {
this.container = document.getElementById(id);
this.options = opts;
this.container.innerHTML = this.render(opts.data);
}
registerPlugins(...plugins) {
//abstract
};
render(data) {
//abstract
return "";
}
}extend
关键字来继承这个component。
总结
- 组件设计的原则:封装性、正确性、复用性、扩展性
- 实现组件的步骤:结构设计、展现效果、行为设计
- 三次重构
- 插件化
- 模板化
- 抽象化