[Vue音乐项目] 第四节 轮播图

既然上节已经获取到数据,那么本节将使用轮播图展示这些数据,轮播图属于常用组件,可以独立成一个公共组件。

  1. 打开cmd命令行安装better-scroll(借助插件实现轮播图,后面也会用到)
    npm install better-scroll --save-dev
    
  2. 在src/base目录下(没有的话先创建)创建slider目录,并在目录下创建slider.vue文件
    //slider.vue 先简写html文件
    <template>
        //轮播图容器,宽度一般为:轮播图宽度(或自定义宽度)
        <div class="slider" ref="slider"> //第4步提前写[1]
            //图片组容器,宽度一般为:轮播图宽度 * (轮播图数量+2)
            <div class="slider-group ref="sliderGroup">  //第4步提前写[2]
                //Vue插槽,由父组件放置轮播图
                <slot></slot>
            </div>
            //滚动点容器,显示当前图片的序号
            <div class="slider-dots>
                //当前图片对应的点会放大,滚动点的数量为轮播图的数量
                <span class="dot" :class="active: current == index" 
                v-for="(item,index) in dots" :key="index">
                </span>  第4步提前写[3]
            </div>
        </div>
    </template>
    <script>
        ...
    </script>
    <style scoped lang="stylus">
        .slider /* 轮播图样式提前写好 */
            position: relative /* 设置相对定位,使得滚动点能够定位 */
            min-height: 1px
            .slider-group
                position: relative /* 设置相对定位,使得能够滚动图片位置 */
                overflow: hidden
                white-space: nowrap
                .slider-item  /* 这是插槽里单个轮播图的样式,需要动态添加 */
                    float: left
                    box-sizing: border-box
                    overflow: hidden
                    text-align: center
                    img 
                        display: block
                        width: 100%
            .slider-dots
                display: absolute  /* 绝对定位 */
                left: 0     /* left + right 使得元素宽度为父元素宽度 */
                right: 0 
                bottom: 12px
                text-align: center /* text-align + font-size 使得子元素能够水平居中 */
                font-size: 0
                .dot
                    display: inline-block
                    width: 8px
                    height: 8px
                    border-radius: 50%  /* 宽高相等 + 50%圆角 = 圆点 */
                    background-color: $color-text-l
                    &.active  /* 轮播图对应的滚动点,添加点特别的样式 */
                        width: 20px;
                        border-radius: 5px
                        background-color: $color-text-ll
                
            
    </style>
    
    轮播图原理:首先定义一个轮播图容器,内含两个div,一个存放图片的容器(图片组容器),另一个存放滚动点的容器(滚动点容器)。一般来说,轮播图容器宽度为设置好的轮播图宽度,而图片组宽度为轮播图宽度 * (轮播图数量+2),多出来的两个宽度用于复制第一个及最后一个轮播图,使得轮播效果顺滑不突兀。轮播图的要点是,图片组容器必须比轮播图容器宽度长,这是使得轮播图能够轮播的真正要点。
  3. 打开src/componnents/recommend/index.vue文件,目前还没有图片显示,接下在父组件导入该组件并放置轮播图。
    //index.vue
    <template>
      <div class="recommend">
        <div class="content">
            //第二步,使用轮播图组件
            <slider v-if="recommends">
                //这里编写的内容将放入轮播图的插槽里,也是.slider-item应用的元素
                <div v-for="(item,index) in recommends" :key="index">
                    //遍历图片地址并放入img标签里
                    <img :src="item.picUrl" alt="">
                </div>
            </slider>
            <div class="list">
            <!-- <h1>热门歌单推荐</h1> -->
            </div>
        </div>
      </div>
    </template
    <script>
        //第一步,导入轮播图组件
        import slider from 'base/slider'
        export default {
            data() {
                return {
                    //存放的轮播图数据,由jsonp函数获得
                    recommend: null
                }
            }
        }
    </script>
    <style>
        ....
    <style>
    
  4. 返回src/base/slider/index.vue文件,完成数据的填充后,开始编写逻辑代码让轮播图东起。
    //index.vue
    <template>
        ...
    </template>
    <script>
        //导入better-scroll插件
        import Srcoll from 'better-scroll'
        export default {
            //选择在vue实例挂载后执行,避免宽度获取不到的问题
            mounted() {
                //第一步 设置轮播图宽度
                this._initSliderWidth()
                //第二步 初始化轮播点
                this._initDots()
                //第三步 启动轮播器,并监听其变化
                this._initSlider()
                //第四步 自动播放[2]
                if(this.slider) {
                    this._play()
                }
            },
            methods: {
                //1.初始化轮播图容器,图片组容器,轮播图的宽度,并给轮播图添加样式
                _initSliderWidth() {
                    //有轮播图的数组引用,用到第2步提前写的ref(reference,即引用,实际是dom对象) 
                    //第1步提前写[1]
                    this.children = this.$refs.sliderGroup.children
                    //图片组容器的宽度
                    var width = 0;
                    //轮播图容器的宽度 第1步提前写[2]
                    var sliderWidth = this.$refs.slider.clientWidth
                    for(let i=0; i<this.children.length; i++) {
                        //给每个轮播图添加样式
                        addClass(this.children[i],'slider-item')
                        //设置轮播图的宽度为轮播图容器的宽度
                        this.children[i].style.width = sliderWidth + 'px'
                        //计算图片组容器的宽度
                        width += sliderWidth
                    }
                    //循环播放的话,加上两个轮播图的宽度
                    if(this.loop) {
                        width += 2*sliderWidth
                    }
                    //给轮播图容器设置长度
                    this.$ref.sliderGroup.style.width = width + 'px'
                }
                //2.初始化滚动点
                _initDots() {
                    this.dots = new Array(this.children.length)
                }
                //3.启动轮播图
                _initSlider() {
                    //3.1 实例化better-scroll
                    this.slider = new Scroll(this.$refs.slider,{
                        scrollX: true,  //滚动x轴
                        scrollY: false,
                        momentum: false,
                        snap: {
                            loop: this.loop,
                            threshold: 0.3,
                            speed: 400
                        },
                        click: true
                    })
                    //3.2 监听better-scroll,改变滚动点的样式 第1步提前写[3]
                    this.slider.on('srcollEnd',function(){
                        //更新当前图片索引
                        thish.current = this.slider.getCurrentPage().scrollX
                        //自动播放[3]
                        if(this.autoplay) {
                            clearTimeout(timer)
                            this._play()
                        }
                    })
                }
                4. 自动播放[1]
                _play() {
                    //获取下一张图片的索引
                    var next = (this.current + 1) > 4 ? 0 : this.current + 1
                    //设置定时器 ps:使用timeout而不是interval
                    this.timer = setTimeout(()=>{
                        this.slider.goToPage(next,0,400)
                    },this.interval)
                }
            },
            destroyed() {
                //自动播放[4] : 组件销毁时,清楚定时器
                clearTimeout(this.timer) 
            }
        }
    </script>
    <style>
        ...
    </style>
    
posted @ 2020-10-22 21:46  绝弹笔记  阅读(190)  评论(0编辑  收藏  举报