JavaScript(2) | 青训营笔记

72 阅读3分钟

这是我参与「第四届青训营 」笔记创作活动的第7天

这节课的三要点 之二

组件封装

好的UI组件具备正确性、扩展性、复用性。

这个我也是知道的,自己的理解是:就好像js里的函数,可以复用的函数可以封装,便于维护,修改,拓展复用。

接着月影老师放出了另一个常见的小例子,电商网站的轮播图

2022-08-08_213149.png

之前也有写过,但是似乎忘了点

那就趁着这个机会,在复习一遍吧

先看代码

html :

<div id="my-slider" class="slider-list">
  <ul>
    <li class="slider-list__item--selected">
      <img src="https://p5.ssl.qhimg.com/t0119c74624763dd070.png"/>
    </li>
    <li class="slider-list__item">
      <img src="https://p4.ssl.qhimg.com/t01adbe3351db853eb3.jpg"/>
    </li>
    <li class="slider-list__item">
      <img src="https://p2.ssl.qhimg.com/t01645cd5ba0c3b60cb.jpg"/>
    </li>
    <li class="slider-list__item">
      <img src="https://p4.ssl.qhimg.com/t01331ac159b58f5478.jpg"/>
    </li>
  </ul>
</div>

css :

#my-slider{
  position: relative;
  width: 790px;
}

.slider-list ul{
  list-style-type:none;
  position: relative;
  padding: 0;
  margin: 0;
}

.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;
}

首先html这个界面还好说,用的无序列表 ul & li 并放上图片。

css样式 不难看出,先用定位把4张图放在一个位置,再用用一个类名 selected 来控制某张图片的显示。

小注意点:在这之前先把所有的类名设置成原始样式,在把单独设有selected的展现出来。

接下来是js

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);  
  }
}

const slider = new Slider('my-slider');
slider.slideTo(3);

setInterval(()=>{
slider.slideNext();
},5000)

首先我想说的是,果然很 高级 直接用的class,我记得当时我练习写轮播图时,还是不会这么注意的,看来这种组件封装还是看起来最舒服的。

那就让我先一步步把他读懂吧:

首先

class Slider{
  constructor(id){
    this.container = document.getElementById(id);
    this.items = this.container
    .querySelectorAll('.slider-list__item, .slider-list__item--selected');
  }

用class定义了一个类名Slider

用到了constructor原型对象

所以,当我们 new 一个实例对象时,新创建的实例对象 里面的this会指向这个实例对象

我们直接看到这段代码的后段部分会发现

const slider = new Slider('my-slider');

这里说明已经有了一个slider的对象 并且传递了参数 'my-slider'

这里的 'my-slider' 传递给到了上面class里 constructorid

所以我们就直接带入去看class构造函数吧

1.拿到了id为 'my-slider' 的div盒子 用container保存

2.拿到id为 'my-slider' 的类名下所有类名为 .slider-list__item, .slider-list__item--selected 即所有图片的类名

接着:

getSelectedItem(){
    const selected = this.container
      .querySelector('.slider-list__item--selected');
    return selected
  }

定义方法getSelectedItem():这个方法最终是返回一个被展示的选定的图片标签

getSelectedItemIndex(){
    return Array.from(this.items).indexOf(this.getSelectedItem());
  }

定义方法getSelectedItemIndex(): 返回被展示的标签索引

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';
    }
  }

定义方法slideTo(idx):跳转到指定索引图片

传入一个参数idx即索引,若使用此方法,将会使传入的索引那个对应的图片拿到展示出来的类名'slider-list__item--selected'

slideNext(){
    const currentIdx = this.getSelectedItemIndex();
    const nextIdx = (currentIdx + 1) % this.items.length;
    this.slideTo(nextIdx);
  }

定义方法slideNext():跳转下一张图片

首先,拿到此刻被选中的标签的索引

其次,让此索引+1,并且➗4(即此轮播图的图片数),为了防止当轮播图到最后一张时此时3+1变成了4但是我们没有索引为4的图片,总共只有0 1 2 3

最后使用this.slideTo(nextIdx)跳转到计算好的下一张图片

slidePrevious(){
    const currentIdx = this.getSelectedItemIndex();
    const previousIdx = (this.items.length + currentIdx - 1)
      % this.items.length;
    this.slideTo(previousIdx);  
  }

定义方法slidePrevious():跳转到上一张图片

总觉得方法好复杂,我觉得这样写比较好:

slidePrevious(){
    const currentIdx = this.getSelectedItemIndex();
    const previousIdx = currentIdx===0?3:currentIdx-1;
    this.slideTo(previousIdx);  
  }

就像是上面的下一张图片一样可以用三元表达式

slideNext(){
    const currentIdx = this.getSelectedItemIndex();
    const nextIdx = currentIdx===3?0:currentIdx+1;
    this.slideTo(nextIdx);
  }

这些就是最基本的功能,接下来就是定义按钮和原点了

这样子看来确实整齐的多,想当初自己练习写轮播图很乱....

好了今天先写到这里,明天继续深入!