欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

vue-music (3) 轮播图

程序员文章站 2022-03-07 17:19:12
...

抽象出一个轮播图组件slider

<div class="slider" ref="slider">
    <div class="slider-group" ref="sliderGroup">
      <slot>
      </slot>
    </div>
    <div class="dots">
      <span class="dot" v-for="(item,index) in dots" :key="index" :class="{'active':currentPageIndex === index}"></span>
    </div>
  </div>

slot插槽,将在父组件中包裹着数据带到子组件,然后将完整的子组件返回

props: { // **接受外部组件对该轮播图组件的控制**
    loop: {
      type: Boolean,
      default: true // 设置循环状态
    },
    autoPlay: { // 自动播放
      type: Boolean,
      default: true
    },
    interval: { // 轮播时间间隔
      type: Number,
      default: 3000
    }
},
mounted (){ // mounted钩子函数,初始化better-scroll
    setTimeout(() => { // *页面刷新的时间在17ms左右,所以设置延时20ms,等待dom加载完成*
        this.__setSliderWidth() // 初始化  设置容器宽度
        this._initDots() // 初始化 轮播图下面的小点点
        thsi._initSlider() // 初始化bscroll

        if (this.autoPlay) {
            this._play()
        }
    }, 20)

 // 当改变屏幕大小(横屏)时需要重新计算sliderwidth
    window.addEventListener('resize', () => {
      if (!this.sliderScroll) {
        return // 已经初始化了  就不需要再计算
      }
      this._setSliderWidth(true) // 重新初始化容器宽度 *true为标志*
      this.sliderScroll.refresh() // 调用scroll组件中的refresh()方法刷新
    })
},
destroyed () { // 当页面切走的时候,组件会调用destroyed来销毁实例。所以在这个时候要清除定时器,这是一个好的变成习惯,利于内存的释放
    clearTimeout(this.timer)
},

created()和mounted()差别
created:在模板渲染成html前调用,即通常初始化某些属性值,然后再渲染成视图。使用的较多
mounted:在模板渲染成html后调用,通常是初始化页面完成后,再对html的dom节点进行一些需要的操作,使用较少,在子组件使用,父组件使用created,子组件用mounted。在vue生命周期中只执行一次. slider组件需要等图片数据渲染完才能计算出宽度,所以用mounted()

methods: {
    _setSliderWidth(isResized){ // *判断是否需要重新计算宽度  即有没有横屏情况*
        this.children = this.$refs.sliderGroup.children // 轮播图有多少个li 即有多少张图片
        let winth = 0 // 定义初始width
        let sliderWidth = this.$refs.slider.clientWidth // 定义每个图片的宽度 即屏幕可视区宽度
        for(let i=0; i<this.children;i++){ // 遍历所有图片
            let children = this.children[i]
            addClass(child, 'slider-item') // *调用外部方法*  给每个li 添加新的slider-item的class
            child.style.width = sliderWidth + 'px' // 每个图片 li都赋值width属性 为屏幕宽度 *stylu.width 要有单位*
            width += sliderWidth // 有几个图片,循环几次,就加几次屏幕宽度 最终得到容器总宽度
        }
        if (this.loop && !isResized) { // 当isResized为true时候,就不用再头尾各加一张图片 为了使以下代码就再初始化的时候执行一次
            width += 2 * sliderWidth // 因为循环播放,所以要在头尾各家一张图片
        }
        this.$refs.sliderGroup.style.width = width // 容器ul的宽度就是width
    },
}

addClass()给el添加class属性的方法

// addClass()
    function addclass(el, claName){
        if (hasClass(el, claName){
            return // 若有该class 直接返回
        }
        let ClassArr = el.className.split('') // 将el所有的class拆成数组
        ClassArr .push(claName) // 将新class插入到el的class数组中
        el.className = ClassArr .join('') // 将class数组变成字符串
    }
    // 添加之前先判断有没有该class
    function hasClass(el, claName){
        let reg = new RegExp('(^|\\s)' + claName + '(\\s|$)') // 正则判定
        return reg.test(el.claName) 
    }   

methods: {
    _initSlider(){   // BScroll初始化 设置
        this.sliderScroll = new BScroll(this.$refs.slider, {
            scrollX: true,  // 横向滑动
            scrollY: false, // 竖向滑动
            momentum: false,
            snap: {  // 轮播设置
              loop: this.loop, // 循环
              threshold: 0.3, // 动画时间
              speed: 400 // 轮播间隔
            }
         })
         this.sliderScroll.on('scrollEnd', () => { // BScroll 自带监听事件, 监听滚动结束后,执行回调函数
            let pageIndex = this.sliderScroll.getCurrentPage().pageX   // BScroll自带方法 获得当前图片***
            this.currentPageIndex = pageIndex // 通过此值,动态给 小点点 active 属性
         })
         if (this.autoPlay) { // 防止手动滑动,它又自己滑动顺序错乱
            clearTimeout(this.timer) // 每次轮播一张后去掉定时器
            this._play()
         }
    },
    _initDots(){
        this.dots = new Array(this.children.lenfth) // 几个li就几个点点
    }
    _play(){ // 真正轮播的函数
        this.setTimeout(() => {
            this.sliderScroll.next() // BScroll内置方法, 跳到下一张
        },this.interval) // 可以接受父组件传值
    }
 }

通过 :class 计算属性动态加active

<span class="dot" v-for="(item,index) in dots" :key="index" :class="{'active':currentPageIndex === index}"></span>

vue-music (3) 轮播图
vue-music (3) 轮播图
vue-music (3) 轮播图

相关标签: vue