【四】轮播图组件

关于专题【vue开发音乐App】 轮播图属于基础组件,所以归纳到src/base/slide里面,新建slide.vue 一、html部分 .slider作为最外层包裹,里面有两个元素:一个是包含所有.slider-item的.slider-group、另一个是包含所有.dot的.dots 为了使该组件更灵活,组件并不限定滑动元素必须是img,而是提供了一个插槽slot,你可以放置所有你想放置的元素,比如div、p等 为.slider-group添加ref="sliderGroup"是为了通过this.$refs.sliderGroup.children获取所有轮播元素的dom,以给它们都添加"slider-item"类 为.slider添加ref="slider"是为了获取父容器.slider的宽度,这样才能设置每一个轮播元素.slider-item的宽度与父容器的相等,继而能计算出包裹它们的.slider-group的宽度(累加和) 二、js部分 js代码100余行,全部展开不利于浏览,所以先看整体结构: 首先安装better-scroll:cnpm i better-scroll -S 引入better-scroll以及专题【三】中dom.js里的addClass方法 name: 'slider':意味着使用方法为 props props: { loop: { type: Boolean, default: true }, autoPlay: { type: Boolean, default: true }, interval: { type: Number, default: 4000 } }, loop:是否循环播放?默认:是 autoPlay:是否自动播放?默认:是 interval:切换时间间隔,单位:毫秒,默认:4000 data data () { return { dots: [], currIndex: 0 } }, dots:轮播图组件上的小圆点,数组长度等于元素.slider-item的个数 currIndex:表示当前播放的是第几张,通过匹配循环索引,给当前项的小圆点添加active类(变成长条圆角状) mounted mounted () { setTimeout(() => { this._setSliderWidth() this._initDots() this._initSlider() if (this.autoPlay) { this._play() } }, 20) // 浏览器刷新一般需要17毫秒 window.addEventListener('resize', () => { if (!this.slider) { return false } this._setSliderWidth(true) this.slider.refresh() }) }, 由于浏览器刷新通常花费17毫秒,所以为了保证dom成功渲染,需要在mounted钩子中,设置一个20毫秒的延时,20毫秒之后,再执行: _setSliderWidth():获取轮播图宽度 _initDots():初始化小圆点 _initSlider():初始化轮播图 _play():如果允许自动播放就执行播放 监听window的resize事件,发现窗口尺寸变化,就重新设置轮播图宽度为当前窗口宽度、调用better-scroll组件的refresh方法 methods methods: { _setSliderWidth (isResize) {...}, _initDots () {...}, _initSlider () {...}, _play () {...} } _setSliderWidth() // 获取轮播图宽度 _setSliderWidth (isResize) { this.children = this.$refs.sliderGroup.children let width = 0 let sliderWidth = this.$refs.slider.clientWidth for (let i = 0; i < this.children.length; i++) { let child = this.children[i] addClass(child, 'slider-item') child.style.width = sliderWidth + 'px' width += sliderWidth } // 如果是循环播放,一头一尾需要多放一个dom if (this.loop && !isResize) { width += 2 * sliderWidth } this.$refs.sliderGroup.style.width = width + 'px' }, this.$refs.sliderGroup.children获取所有轮播元素的dom,给它们添加"slider-item"类 this.$refs.slider.clientWidth获取父容器的宽度sliderWidth(实际上是视窗宽度) 设置.slider-item的宽度等于sliderWidth 设置.slider-group的宽度等于所有.slider-item宽度累加的和 _initDots() // 初始化小圆点 _initDots () { this.dots = new Array(this.children.length) }, new一个this.children.length长度的数组,我们只关心this.dots的长度,至于数组的每一项是空(empty)还是有值,都不影响小圆点渲染 _initSlider() // 初始化轮播图 _initSlider () { this.slider = new BScroll(this.$refs.slider, { scrollX: true, scrollY: true, momentum: false, // 惯性 snap: true, snapLoop: this.loop, snapThreshold: 0.3, snapSpeed: 400 }) this.slider.on('scrollEnd', () => { let pageIndex = this.slider.getCurrentPage().pageX if (this.loop) { pageIndex -= 1 } this.currIndex = pageIndex if (this.autoPlay) { clearTimeout(this.timer) this._play() } }) }, new BScroll:创建一个better-scroll的实例 第一个参数是一个原生的 DOM 对象。如果传递的是一个字符串,better-scroll 内部会尝试调用 querySelector 去获取这个 DOM 对象,所以初始化代码也可以是这样:let scroll = new BScroll('.wrapper') 第二个参数是一个对象,包含了一些配置,详见文档 getCurrentPage().pageX:在横轴方向上获取当前页面索引pageIndex _play() // 播放 _play () { let index = this.currIndex + 1 if (this.loop) { index += 1 } this.timer = setTimeout(() => { this.slider.goToPage(index, 0, 400) }, this.interval) } 该函数设置了一个计时器,在规定的时间内(this.interval)执行一次BScroll对象的goToPage方法 参数一: x 横轴的页数 参数二: y 纵轴的页数 参数三: 动画执行的时间 destoryed destoryed () { clearTimeout(this.timer) } 三、css部分 通过@import引入外部公用css:variable.styl .slider-item被设置了左浮动,从而使所有滑动元素横向排成一排 .slider-group规定子元素不换行

本文章由javascript技术分享原创和收集

发表评论 (审核通过后显示评论):