javascript学习笔记 | 青训营笔记

378 阅读3分钟

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,灵活性高。

模板化轮播图

组件框架

实现的组件框架将组件通用模型抽象出来,利用继承来实现轮播图,能完成多种不同样式的轮播图,进一步提高了灵活性,复用性。

组件化轮播图

总结

  • 组件设计原则:封装性,正确性,扩展性,复用性
  • 实现组件的步骤:结构设计,展现效果,行为设计
  • 三次重构:
    • 插件化

    • 模板化

    • 抽象化