JavaScript(3) | 青训营笔记

76 阅读2分钟

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

书接上文JavaScript(2) | 青训营笔记 - 掘金 (juejin.cn)

好了,接下来就是实现,左右按钮和底部小圆点的功能

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

不难看出,这里是在定义了小圆点和左右按钮

重头戏在这里 js

constructor相比之前添加了许多代码:

所有的代码就不放出来了,一点一点的在代码里的 注释里来解释

第一部分,鼠标经过小圆点-控制图片切换

constructor(id, cycle = 3000){
    this.container = document.getElementById(id);
    this.items = this.container.querySelectorAll('.slider-list__item, .slider-list__item--selected');
    this.cycle = cycle;
    //1.拿到放小圆点按钮的盒子
    const controller = this.container.querySelector('.slide-list__control');
    if(controller){
    //2.拿到所有小圆点(选中或未选中的)
      const buttons = controller.querySelectorAll('.slide-list__control-buttons, .slide-list__control-buttons--selected');
     //3.给当前放小圆点的盒子添加鼠标经过事件
      controller.addEventListener('mouseover', evt=>{
      //4.拿到小圆点的索引(从buttons里拿),若鼠标只经过盒子,则返回值为-1
        const idx = Array.from(buttons).indexOf(evt.target);
        //5.如果拿到了(如果经过了4个圆点的某一个)
        if(idx >= 0){
          //6.使用slideTo(idx),跳转到指定索引下的图片
          this.slideTo(idx);
          //7.并且停止轮播图的自动播放
          this.stop();
        }
      });
      //8.鼠标离开开启自动切换
      controller.addEventListener('mouseout', evt=>{
        this.start();
      });
      
      //9.接下来就是小圆点的样式切换
      this.container.addEventListener('slide', evt => {
        const idx = evt.detail.index
        const selected = controller.querySelector('.slide-list__control-buttons--selected');
        if(selected) selected.className = 'slide-list__control-buttons';
        buttons[idx].className = 'slide-list__control-buttons--selected';
      })
    }

在第 9 点时这里就有我之前没有学到过的点: evt.detail.index

虽然很容易知道是干什么的但是还真是没有用到过

通过听月影老师的讲解发现,是自定义监听事件

自定义事件 解耦

首先此处监听的是container即整个标签的 'slide' 事件,此处的slide是自定义事件

小圆点的状态和图片的状态进行绑定

定义一个detail,要传入一个值,这里传入了一个索引
   const detail = {index: idx}
   //创造一个自定义事件实例 两个值传进去了(事件冒泡:true detail:idx)
   const event = new CustomEvent('slide', {bubbles:true, detail})
   //绑定到到这个轮播图里的事件对象上开始监听,监听 **'silde'**事件
   this.container.dispatchEvent(event)

接着就是左右按钮的 js 代码

//1.左按钮绑定点击事件
    const previous = this.container.querySelector('.slide-list__previous');
    if(previous){
      previous.addEventListener('click', evt => {
        //(1).关闭自动切换轮播图动画
        this.stop();
        //(2).切换到上一页
        this.slidePrevious();
        //(3).开启自动切换动画
        this.start();
        evt.preventDefault();
      });
    }
//2.右按钮绑定事件
    const next = this.container.querySelector('.slide-list__next');
    if(next){
      next.addEventListener('click', evt => {
        this.stop();
        this.slideNext();
        this.start();
        evt.preventDefault();
      });
    }

但是这里 evt.preventDefault();阻止点击的默认事件,不知道是干嘛用的,有和无都是可以实现效果的

接下来就是轮播图的自动切换了,特别注意,在开始动画前一定是先停止一下,防止前面的动画没有结束,就再有一个定时器。

start(){
    this.stop();
    this._timer = setInterval(()=>this.slideNext(), this.cycle);
  }
  stop(){
    clearInterval(this._timer);
  }

这个时候就把整个轮播的案例搞定了。

但是!!!还是有优化的空间。

不知不觉已经写了很多了,剩下的明天继续!!