better-scroll 实现无缝轮播
better-scroll 适用于解决移动端各种滚动场景,滚动列表、轮播图等。better-scroll新版本设置轮播图有一些变动。slider.vue:结构及部分样式设置:<div class="slider" ref="slider"><div class="slider-group" re
·
better-scroll 适用于解决移动端各种滚动场景,滚动列表、轮播图等。
better-scroll新版本设置轮播图有一些变动。
slider.vue:
结构及部分样式设置:
<div class="slider" ref="slider">
<div class="slider-group" ref="sliderGroup">
<slot> //插槽位置即轮播图,在引入主页面的中间插入图片
</slot>
</div>
<div class="dots"> //小圆点采用绝对定位
<span class="dot" :class="{active:currentIndex === index}" v-for="(item, index) in dots" :key="index" ></span>
</div>
</div>
<style rel="stylesheet/stylus" lang="stylus">
@import "~common/stylus/variable"
.slider
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
a
display: block
width: 100%
overflow: hidden
text-decoration: none
img
display: block
width: 100%
</script>
recommend.vue:
<div class="slider-wrapper">
<div v-if="recommends.length" class="slider-wrapper">
<slider> //以下就是插槽的内容
<div v-for="(item, index) in recommends" :key = "index">
<a :href="item.linkUrl">
<img class="needclick" :src="item.picUrl">
</a>
</div>
</slider>
</div>
</div>
其中需要注意,这边需要控制显示的时机,是由于slider.vue中设置html的宽度等是在mounted (即已完成模板渲染后执行),而recommend.vue 当还未获取数据的时候,mounted 已经执行,为了确保元素的存在再渲染,所以添加判断。
slider.vue,设置图片的宽度以及总宽度:
_setSliderWidth(isResize) {
this.children = this.$refs.sliderGroup.children
let width = 0
let slideWidth = 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 = slideWidth + 'px'
width += slideWidth //容器的总宽度
}
if (this.loop && !isResize) {
width += 2 * slideWidth //如果轮播,左右会各增加一个,所以要加上两张图片的宽度
}
this.$refs.sliderGroup.style.width = width + 'px' //为元素设置容器的总宽度
},
addClass :(添加类名)
export function hasClass(el, className) {
let reg = new RegExp('(^|\\s)' + className + '(\\s|$)') //判断className 的开头或结尾无字符或者是空格
return reg.test(el.className)
}
export function addClass(el, className) {
if (hasClass(el, className)) { //有这个类名就返回
return
}
let newClass = el.className.split(' ') //split() 将原本的className字符串按空格分割成数组
newClass.push(className) //将新的className 添加到上面的数组中
el.className = newClass.join(' ') //join() 以空格为连接符链接成class字符串
}
拓展:
//删除class
export function removeClass(el, className) {
//先判断是否含有这个class,含有时,才继续
if (!hasClass(el, className)) {
return
}
let newClass = el.className.split(' ') //分割class字符串为class数组
let index = newClass.findIndex((item)=>{ //找到指定的class在class数组中的索引
return item === className
})
newClass.splice(index,1) // 删除索引中的这项
el.className = newClass.join(' ') //将class数组以空格为连接符连接成class字符串
}
初始化 better-scroll时机,将那些函数在mounted 完成渲染后执行:(*一般初始化better-scroll不成功);
并通过监听窗口改变事件,解决当窗口改变时,图片的宽度未发生改变的问题
mounted() {
this._setSliderWidth()
setTimeout(() => {
this._initDots()
this._initSlider()
if (this.autoPlay) {
this._play()
}
}, 20) //保证DOM被渲染,做了20ms的延时(*为何值为20??* 因为浏览器刷新时间一般为17ms一次)
window.addEventListener('resize', () => { //监听窗口改变事件,解决当窗口改变时,图片的宽度未发生改变的问题
if (!this.slider) {
return
}
this._setSliderWidth(true)
this.slider.refresh()
})
初始化better-slider插件:
_initSlider() {
this.slider = new BScroll(this.$refs.slider, {
scrollX: true, //横向滚动
scrollY: false, //不允许纵向滚动
momentum: false, //关闭动量动画,能提升效能
snap: { //新版本将snap的属性都当成一个对象来书写
loop: this.loop, //循环
threshold: 0.3,
speed: 400 //轮播间隔
},
click: true
})
this.slider.on('scrollEnd', () => {
let pageIndex = this.slider.getCurrentPage().pageX //轮播到下一张,获取当前的index
// if (this.loop) { //旧版本设置方式,新版本不需要
// pageIndex -= 1
// }
this.currentIndex = pageIndex
if (this.autoPlay) {
clearTimeout(this.timer) //如果设置额自动轮播就清除轮播再重新启动
this._play()
}
})
},
新版本的dots没有改变设置:
_initDots() {
this.dots = new Array(this.children.length)
},
播放就可以采用更便捷的命令:
_play() {
// let pageIndex = this.currentIndex + 1 //旧版本需要计算增加的两张图片带来的影响
// if (this.loop) {
// pageIndex += 1
// }
this.timer = setTimeout(() => {
this.slider.next()
}, this.interval)
}
优化:
1. 及时关闭轮播,有利于内存的释放
destroyed() {
clearTimeout(this.timer)
}
2. app.vue中添加<keep-alive>,将DOM缓存到内存中,切换不会重新请求,并且没有一闪而过的画面
<keep-alive>
<router-view></router-view>
</keep-alive>
更多推荐
已为社区贡献4条内容
所有评论(0)