javascript学习笔记 | 青训营笔记
这是我参与「第四届青训营 」笔记创作活动的第3天
一个简单案例
切换文章的夜间与日间模式
初始js代码:
const btn = document.querySelector('#btn');
btn.addEventListener('click',(e)=>{
const body = document.body;
if(e.target.innerHTML==='☀'){
body.style.backgroundColor = 'black';
body.style.color = 'white';
e.tartget.innerHTML = '🌙'
}else{
body.style.backgroundColor = 'white';
body.style.color = 'black';
e.tartget.innerHTML = '☀'
}
})
可见js直接操控了样式,但代码不能复用且冗余,其他人读起来语义不明,修改不便,有很高的修改空间。
修改后:
const btn = document.querySelector('#btn');
btn.addEventListener('click',(e)=>{
const body = document.body;
if(body.className !=='night'){
body.className = 'night';
}else{
body.className = '';
}
})
修改后,js仅操控了body的class,而没有接触到css,若有修改的需求可以直接修改css,而不是修改js。
再次修改后:
/*css*/
#modeCheckBox{
display : none;
}
#modeCheckBox:checked + .content{
background-color: black;
color: white;
}
<input id="modeCheckBox" type="checkbox">
<div class="content">
<label id="modeBtn" for="modeCheckBox"></label>
</div>
再次修改后,成为了纯css代码,不需要js的参与,这样就将样式与js彻底分隔开,避免了不必要的js操控样式,做到了HTML/CSS/JS各司其职。
组件封装
轮播图:
HTML
轮播图是典型列表结构,所以可以用无序列表来实现
CSS
每个li标签中插入一张图片,然后利用css的绝对定位,使图片重合在一起。
其中,未被选择的图片opacity置为0,使之透明不可见。已选择的图片则将opacity置为1;
.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;
}
由于已选择元素与被选择元素有一些相似性,所以共同设置样式,又由于有不同点,故要将被选择的元素单独添加样式。
JS
在JS中,单独定义了一个Slider类用于控制样式的改变
Slider类中有一个构造方法,用于将所有的li元素保存进items。参数为一个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方法
用于获取已经被选择的元素在items中的位置。
return Array.from(this.items).indexOf(this.getSelectedItem());
slideTo方法
用于选择指定次序的图片,需要一个参数idx,代表图片在items中的位置。将已选择的图片取消选择,将传入的items[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);
为防止nextIdx过大,故采用取余的方式。
slidePrevious方法
用于轮播图滑动向上一张图片
const currentIdx = this.getSelectedItemIndex();
const previousIdx = (this.items.length + currentIdx - 1) % this.items.length;
this.slideTo(previousIdx);
为防止previousIdx产生负数或0,故加上了items的长度并取余。
这种方式灵活性较差,仍有优化空间。
插件化
将轮播图中的左右键与下方原点以插件的形式插入轮播图,方便了轮播图的扩展和维护。但删除插件后,控件仍保留在HTML中,没有实际作用。
模板化
模板化让轮播图能动态的生成HTML模板,添加图片时仅须修改js代码,而不必改动HTML,将JS与HTML的依赖分开。当不需要某插件时,可以直接删除插件,而不用改动html,灵活性高。
组件框架
实现的组件框架将组件通用模型抽象出来,利用继承来实现轮播图,能完成多种不同样式的轮播图,进一步提高了灵活性,复用性。
总结
- 组件设计原则:封装性,正确性,扩展性,复用性
- 实现组件的步骤:结构设计,展现效果,行为设计
- 三次重构:
-
插件化
-
模板化
-
抽象化
-