这是我参与「第五届青训营 」伴学笔记创作活动的第 6 天
前言
- 怎么样才能写好javaScript
- 什么是组件封装
- 什么是高阶函数
写好js的一些原则:
- 各司其职
- 组件封装
- 过程抽象
(一)各司其职
- HTML/CSS/JS各司其责
- 应当避免不必要的由JS直接操作样式
- 可以用class来表示状态
- 纯展示类交互寻求零JS方案
(二)组件封装
组件概念:Web页面上抽出来一个个包括模板(HTML),功能(JS)和样式(CSS)的单元。好的组件具备封装性,正确性,扩展性,复用性。
总结:
- 组件设计的原则:封装性,正确性,扩展性,复用性
- 实现组件的步骤:结构设计,展现效果,行为设计
- 三次重构
- 插件化
- 模板化
- 抽象化(组件框架)
(三)过程抽象
- 用来处理局部细节控制的一些方法
- 函数式编程思想的基础应用
组件封装的例子:
用原生JS写一个电商网站的轮播图,应该如何实现?
结构设计:HTML
轮播图是一个典型的列表结构,可以使用无序列表< ul >元素实现<div id="my-slider"class='slider-list'>
<ul>
<li class="slider-list__item--selected">
<img src="https://p5.ssl.qhimg.com/t0119c74624763dd070.png" alt="">
</li>
<li class="slider-list__item">
<img src="https://p4.ssl.qhimg.com/t01adbe3351db853eb3.jpg" alt="">
</li>
<li class="slider-list__item">
<img src="https://p2.ssl.qhimg.com/t01645cd5ba0c3b60cb.jpg" alt="">
</li>
<li class="slider-list__item">
<img src="https://p4.ssl.qhimg.com/t01331ac159b58f5478.jpg" alt="">
</li>
</ul>
</div>
展现效果:CSS
- 使用CSS绝对定位将图片重叠在同一个位置
- 轮播图切换的状态使用修饰符(modifier)
- 轮播图的切管动画使用CSS(transition)
*{
margin: 0;
padding: 0;
}
li{
list-style: none;
}
a{
text-decoration: none;
color: inherit;
}
#my-slider{
position: relative;
width: 790px;
}
.slider-list ul{
list-style-type: none;
position: relative;
}
.slider-list__item,
.slider-list__item--selected{
position: absolute;
transition: opacity 1s;
opacity: 0;
text-align: center;
}
.slider-list__item--selected{
transition: opacity 1s;
opacity: 1;
}
行为设计:API(JS)
- API设计应保证原子操作,职责单一,满足灵活性。
- Slider
- +getSelectedItem()
- +getSelectedItemIndex
- +slideTo()
- +slideNext
- +slidePrevious()
class 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)
}
}
行为设计:控制流
<a class="slide-list__next"></a>
<a class="slide-list__previous"></a>
<div class="slide-list__control">
<span class="slide-list__control-buttons--selected"></span>
<span class="slide-list__control-buttons"></span>
<span class="slide-list__control-buttons"></span>
<span class="slide-list__control-buttons"></span>
</div>
const detail={index:idx};
const event=new CustomEvent('slide',{bubble:true,detail});
this.container.dispatchEvent(event)
改进空间:
- 重构:插件化
- 将控制元素抽取成插件
- 插件与组件之间通过依赖注入方式建立联系
- 重构:模板化
- 将HTML模板化
- 重构:组件框架
- 将通用的组件模型抽象出来
- 以函数作为参数
- 以函数作为返回值
- 常用于作为函数装饰器