这是我参与「第五届青训营 」伴学笔记创作活动的第 9 天,本节课👩🏻🏫通过一个轮播图例子,让我们知道了组件封装的过程,主要包括结构设计,这个是最重要的,先把结构设计好,然后是展现效果模拟,最后是行为设计包括一些api和event事件
组件封装
组件定义:指web页面上抽出来一个个包含模版(html)、功能(js)和样式(css)的单元,好的组件具备封装性、正确性、扩展性、复用性。
例子:用原生js写一个电商网站的轮播图
结构设计: HTML
轮播图是一个典型的列表结构,我们可以使用无序列表<ul>元素来实现
<div id="app" class="app-list">
<ul>
<li class="app-list__item-selected">
<img src="https://images.unsplash.com/photo-1617709612173-d820eb8b862f?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHx0b3BpYy1mZWVkfDJ8NnNNVmpUTFNrZVF8fGVufDB8fHx8&auto=format&fit=crop&w=800&q=80">
</li>
<li class="app-list__item">
<img src="https://images.unsplash.com/photo-1666705040497-1890be6e357c?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=800&q=80">
</li>
<li class="app-list__item">
<img src="https://images.unsplash.com/photo-1674318012388-141651b08a51?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=800&q=80">
</li>
<li class="app-list__item">
<img src="https://images.unsplash.com/photo-1674240568812-d7481f3699a7?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=800&q=80">
</li>
</ul>
</div>
表现: CSS
- 使用css绝对定位将图片重叠在同一个位置
- 轮播图切换的状态使用修饰符(modifier)
- 轮播图的切换动画使用 CSS transition
#app {
position: relative;
width: 820px;
}
.app-list ul {
list-style-type: none;
position: relative;
padding: 0;
margin: 0;
}
.app-list__item,
.app-list__item-selected {
position: absolute;
transition: opaticy 1s;
opacity: 0;
text-align: center;
}
.app-list__item-selected {
transition: opacity 1s;
opacity: 1;
}
行为:JS
- API设计应保证原子操作,职责单一,满足灵活性
- Slider
- getSelectedItem()
- getSelectedItemIndex()
- slideTo()
- slideNext()
- slidePrevious()
class app {
constructor(id) {
this.container = document. getElementById(id);
this.items = this.container
.querySelectorAll('.app-list__item,.app-list__item--selected');
}
getSelectedItem() {
const selected = this.container
querySelector('.app-list__item--selected');
return selected
}
getSelectedItemIndex() {
return Array.from(this. items).indexof(this.getSelectedItem());
}
slideTo(idx) {
const selected = this.getSelectedItem();
if(selected){
selected.className = "app-list__item";
}
const item = this.items[idx];
if(item) {
item.className = 'app-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);
}
}
行为:控制流
- 使用自定义事件来解耦
<a class="app-listnext"></a>
<a class="app-list__previous">s/a>
<div class="app-list__control">
<span class="app-list__control-buttons--selected"></span>
<span class="app-list__control-buttons"></span>
<span class="app-list__control-buttons"></span>
<span class="app-list__control-buttons"></span>
</div>
const detail = {index: idx}
const event = new CustomEvent('slide',{bubbles:true, detail})
this.container.dispatchEvent(event)
总结:基本方法
-
结构设计
-
展现效果
-
行为设计
-
Api(功能)
-
Event(控制流)
-
解耦
-
将控制元素抽取成插件
-
插件与组件之间通过依赖注入方式建立联系
-
html模板化
抽象:
- 将通用的组件模型抽象出来