vue-music (3) 轮播图

抽象出一个轮播图组件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>

这里写图片描述
这里写图片描述
这里写图片描述

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值