最近在写一个基于vue2.0的移动端音乐项目,昨天写到 了首页的轮播图部分,跟着视频教程写的,没想到最后却出现了一大堆错误,并且都是视频中所没有的,自己思考了很久,也不知道是怎么回事,今天早上开机之后,百度发现,原来是better-scroll的版本为题,视频中用的是老版本"better-scroll": "^0.1.15",而 我npm安装的是新版本"better-scroll": "^1.15.2",,顿时恍然大悟
接下来我主要发一些本次出错误的需要纠正新老版本的部分代码
slider.vue:
<<template>
<div class="slider" ref="slider">
<div class="slider-group" ref="sliderGroup">
<slot>
<!-- 外部引入一个插槽,slider包裹的dom会被引入到插槽部分 -->
</slot>
</div>
<div class="dots">
<span class="dot" v-for="(item,index) in dots" :class="{active: currentPageIndex === index}"></span>
</div>
</div>
</template>
recommend.vue:
<<template>
<div class="recommend">
<div class="recommend-content">
<div v-if="recommends.length" class="slider-wrapper">
<slider>
<div v-for="(item,index) in recommends">
<a :href="item.linkUrl">
<img :src="item.picUrl">
</a>
</div>
</slider>
</div>
<div class="recommend-list">
<h1 class="list-title">热门歌单推荐</h1>
<ul>
</ul>
</div>
</div>
</div>
</template>
其中需要注意,这边需要控制显示的时机,是由于slider.vue中设置html的宽度等是在mounted (即已完成模板渲染后执行),而recommend.vue 当还未获取数据的时候,mounted 已经执行,为了确保元素的存在再渲染,所以添加判断。
slider.vue,设置图片的宽度以及总宽度:
_setSliderWidth(isResize){
this.children = this.$refs.sliderGroup.children
//console.log(this.children.length)
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 //容器的总宽度
}
if (this.loop&&!isResize) {
width += 2*sliderWidth //如果轮播,左右会各增加一个,所以要加上两张图片的宽度
}
this.$refs.sliderGroup.style.width = width+'px' //为元素设置容器的总宽度
},
addClass :(添加类名)
//写一些dom相关操作的代码
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字符串
}
export function hasClass(el,className) {
let reg = new RegExp('(^|\\s)'+className+'(\\s|$)')
//创建一个正则,开头或者是空白字符,class字符跟空白字符,或者结束
return reg.test(el.className)
}//判断是否有class方法
初始化 better-scroll时机,将那些函数在mounted 完成渲染后执行:(*一般初始化better-scroll不成功);
并通过监听窗口改变事件,解决当窗口改变时,图片的宽度未发生改变的问题
mounted(){
setTimeout(() => {
this._setSliderWidth()
this._initDots()
this._initSlider()
if (this.autoPlay) {
this._play()
}
}, 20)
window.addEventListener('resize',()=>{
if (!this.slider) {
return
}
this._setSliderWidth(true)
this.slider.refresh()
})
},
初始化better-slider插件:
_initSlider(){
//初始化slider
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
console.log(pageIndex+1)
// if (this.loop) {
// // pageIndex -= 1
// }旧版本需要,新版本不需要
this.currentPageIndex = pageIndex
if(this.autoPlay){
clearTimeout(this.timer)
// pageIndex -= 1
this._play()
}
})
},
播放就可以采用更便捷的命令:
_play(){
//let pageIndex = this.currentPageIndex + 1
// if (this.loop) {
// pageIndex += 1
// }//旧版本需要计算增加的两张图片带来的影响
this.timer = setTimeout(() => {
// this.slider.goToPage(pageIndex,0,400)
this.slider.next()
}, this.interval);
}
},
优化:
1. 及时关闭轮播,有利于内存的释放
destroyed() {
clearTimeout(this.timer)
}
2. app.vue中添加<keep-alive>,将DOM缓存到内存中,切换不会重新请求,并且没有一闪而过的画面
<keep-alive>
<router-view></router-view>
</keep-alive>