vue利用better-scroll實(shí)現(xiàn)輪播圖與頁(yè)面滾動(dòng)詳解
前言
better-scroll 也很強(qiáng)大,不僅可以做普通的滾動(dòng)列表,還可以做輪播圖、picker 等等...所以本文主要給大家介紹了關(guān)于vue用better-scroll實(shí)現(xiàn)輪播圖與頁(yè)面滾動(dòng)的相關(guān)內(nèi)容,分享出來(lái)供大家參考學(xué)習(xí),下面話不多說(shuō)了,來(lái)一起看看詳細(xì)的介紹吧。
1.安裝better-scroll
在根目錄中package.json的dependencies中添加:
"better-scroll": "^0.1.15"
然后 npm i 安裝。
2.封裝代碼
將better-scroll封裝成兩個(gè)基礎(chǔ)組件slider和scroll放于src/base文件夾中。
slider.vue 代碼
<template>
<div class="slider" ref="slider">
<div class="slider-group" ref="sliderGroup">
<slot>
</slot>
</div>
<div class="dots">
<span class="dot" :class="{active: currentPageIndex === index }" v-for="(item, index) in dots"></span>
</div>
</div>
</template>
<script>
import {addClass} from '../common/js/dom'
import BScroll from 'better-scroll'
export default{
data() {
return {
dots:[],
currentPageIndex: 0
}
},
props:{
loop:{
type:Boolean,
default:true
},
autoPlay:{
type:Boolean,
default:true
},
interval:{
type: Number,
default:4000
}
},
mounted() {
this._setSliderWidth()
setTimeout(() => {
// 在初始化slider前初始化dot
this._initDots()
this._initSlider()
if (this.autoPlay) {
this._play()
}
}, 20)
// 監(jiān)聽(tīng)窗口大小改變時(shí)間
window.addEventListener('resize', () => {
if (!this.slider) {
return
}
this._setSliderWidth(true)
this.slider.refresh()
})
},
methods:{
_setSliderWidth(isResize) {
this.children = this.$refs.sliderGroup.children
let width = 0
// slider 可見(jiàn)寬度
let sliderWidth = this.$refs.slider.clientWidth
for (let i = 0; i < this.children.length; i++) {
let child = this.children[i]
// 設(shè)置每個(gè)子元素的樣式及高度
addClass(child, 'slider-item')
child.style.width = sliderWidth + 'px'
// 計(jì)算總寬度
width += sliderWidth
}
// 循環(huán)播放首尾各加一個(gè),因此總寬度還要加兩倍的寬度
if (this.loop && !isResize) {
width += 2 * sliderWidth
}
this.$refs.sliderGroup.style.width = width + 'px'
},
_initSlider() {
this.slider = new BScroll(this.$refs.slider, {
scrollX: true,
scrollY: false,
momentum: false,
snap: true,
snapLoop: this.loop,
snapThreshold: 0.3,
snapSpeed: 400,
// click:true
})
// 監(jiān)聽(tīng)滾動(dòng)結(jié)束時(shí)間獲取pageX
this.slider.on('scrollEnd', () => {
let pageIndex = this.slider.getCurrentPage().pageX
if (this.loop) {
// 由于bscroll循環(huán)播放首尾各加一個(gè),因此索引-1
pageIndex -= 1
}
this.currentPageIndex = pageIndex
if (this.autoPlay) {
this._play()
}
})
this.slider.on('beforeScrollStart', () => {
if (this.autoPlay) {
clearTimeout(this.timer)
}
})
},
_initDots() {
// 長(zhǎng)度為n的空數(shù)組
this.dots = new Array(this.children.length)
},
_play() {
// currentPageIndex為不含首尾副本的索引,因此若有循環(huán)要+2
let pageIndex = this.currentPageIndex + 1
if (this.loop) {
pageIndex += 1
}
this.timer = setTimeout(() => {
this.slider.goToPage(pageIndex, 0, 400)
}, this.interval)
}
},
// 生命周期destroyed銷毀清除定時(shí)器,有利于內(nèi)存釋放
destroyed() {
clearTimeout(this.timer)
},
}
</script>
<style scoped>
.slider{
min-height: 1px;
position: relative;
}
.slider-group{
position: relative;
overflow: hidden;
white-space: nowrap;
}
.slider-item{
float: left;
box-sizing: border-box;
overflow: hidden;
text-align: center;
height: 150px;
overflow: hidden;
}
.slider-item a{
display: block;
width: 100%;
overflow: hidden;
text-decoration: none;
}
.slider-item img{
display: block;
width: 100%;
}
.dots{
position: absolute;
right: 0;
left: 0;
bottom: 12px;
text-align: center;
font-size: 0;
}
.dot{
display: inline-block;
margin: 0 4px;
width: 8px;
height: 8px;
border-radius: 50%;
background: red;
}
.active{
width: 20px;
border-radius: 5px;
}
</style>
該代碼引用common/js/dom.js中的addClass()方法為每個(gè)輪播圖添加一個(gè)slider-item類,dom.js代碼如下:
export function hasClass (el, className) {
// 開(kāi)始或空白字符+類名+空白字符或結(jié)束
let reg = new RegExp('(^|\\s)' + className + '(\\s|$)')
// 測(cè)試元素是否有該類名,返回布爾值
return reg.test(el.className)
}
export function addClass (el, className) {
if (hasClass(el, className)) {
return
}
// 以空白符為切割位置切割生成新數(shù)組
let newClass = el.className.split(' ')
// 數(shù)組中加入新類名
newClass.push(className)
// 將數(shù)組元素放入一個(gè)字符串,以空白符間隔
el.className = newClass.join(' ')
}
scroll.vue代碼
<template>
<div ref="wrapper">
<slot></slot>
</div>
</template>
<script>
import BScroll from 'better-scroll'
export default {
props: {
probeType: {
type: Number,
default: 1
},
click: {
type: Boolean,
default: true
},
listenScroll: {
type: Boolean,
default: false
},
object: {
type: Object,
default: null
},
data: {
type: Array,
default: null
},
string: {
type: String,
default: ''
},
pullup: {
type: Boolean,
default: false
},
beforeScroll: {
type: Boolean,
default: false
},
refreshDelay: {
type: Number,
default: 20
}
},
mounted() {
setTimeout(() => {
this._initScroll()
}, 20)
},
methods: {
_initScroll() {
if (!this.$refs.wrapper) {
return
}
this.scroll = new BScroll(this.$refs.wrapper, {
probeType: this.probeType,
click: this.click
})
if (this.listenScroll) {
let me = this
// pos為位置參數(shù)
this.scroll.on('scroll', (pos) => {
me.$emit('scroll', pos)
})
}
if (this.pullup) {
this.scroll.on('scrollEnd', () => {
if (this.scroll.y <= (this.scroll.maxScrollY + 50)) {
this.$emit('scrollToEnd')
}
})
}
if (this.beforeScroll) {
this.scroll.on('beforeScrollStart', () => {
this.$emit('beforeScroll')
})
}
},
disable() {
this.scroll && this.scroll.disable()
},
enable() {
this.scroll && this.scroll.enable()
},
refresh() {
this.scroll && this.scroll.refresh()
},
scrollTo() {
this.scroll && this.scroll.scrollTo.apply(this.scroll, arguments)
},
scrollToElement() {
this.scroll && this.scroll.scrollToElement.apply(this.scroll, arguments)
}
},
watch: {
data() {
setTimeout(() => {
this.refresh()
}, this.refreshDelay)
},
string() {
setTimeout(() => {
this.refresh()
}, this.refreshDelay)
},
object() {
setTimeout(() => {
this.refresh()
}, this.refreshDelay)
}
}
}
</script>
<style>
</style>
3.使用封裝組件
使用這兩個(gè)組件的頁(yè)面組件home.vue 代碼如下:
<template>
<div>
<scroll :data="su" class="scroll">
<div>
<div class="slider-wrapper">
<slider>
<div v-for='item in slider'>
<a href="">
<img :src="item.url" alt="">
</a>
</div>
</slider>
</div>
<ul v-for='item in su'>
<li>{{item}}</li>
</ul>
</div>
</scroll>
</div>
</template>
<script>
import Slider from '../base/slider'
import Scroll from '../base/scroll'
export default {
data () {
return {
slider: [
{url: 'http://upload-images.jianshu.io/upload_images/7932253-54c81df0beed405b.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1080/q/50'},
{url: 'https://y.gtimg.cn/music/photo_new/T003R720x288M000004ERTpn1UBu2f.jpg?max_age=2592000&max_age=2592000'},
{url: 'https://y.gtimg.cn/music/photo_new/T003R720x288M00000077s7P0HaZpc.jpg?max_age=2592000&max_age=2592000'},
{url: 'https://y.gtimg.cn/music/photo_new/T003R720x288M000001QL1Si05yMPq.jpg?max_age=2592000&max_age=2592000'},
{url: 'https://y.gtimg.cn/music/photo_new/T003R720x288M000002ke7OC3ooZ5g.jpg?max_age=2592000&max_age=2592000'},
],
su:[1,2,3,4,5,6,7,8,9,10,1,2,3,4,2,3,5,8,7,4,]
}
},
methods: {
},
components: {
Slider,
Scroll
}
}
</script>
<style>
.slider-wrapper{
width: 100%;
position: relative;
overflow: hidden;
}
.scroll{
height: 500px;
}
</style>
注意點(diǎn):
slider組件的父元素必須給他一個(gè)100%的寬度且定義overflow:hidden,否則整個(gè)頁(yè)面會(huì)被撐開(kāi),整個(gè)頁(yè)面都能橫向滾動(dòng)
scroll組件在引用時(shí)必須給他一個(gè)固定高度。只有擁有固定高度才會(huì)發(fā)生滾動(dòng)。
效果圖如下:

總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,本文還有許多不足,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
Vue3中虛擬dom轉(zhuǎn)成真實(shí)dom的過(guò)程詳解
Vue.js?在其運(yùn)行過(guò)程中會(huì)將模板編譯成虛擬?DOM?(VNode),然后再將?VNode?渲染成實(shí)際的?DOM?節(jié)點(diǎn),這個(gè)過(guò)程是由?Vue?內(nèi)部的編譯器和渲染系統(tǒng)完成的,本文給大家介紹了Vue3中虛擬dom轉(zhuǎn)成真實(shí)dom的過(guò)程,需要的朋友可以參考下2024-09-09
vue的index.html中獲取環(huán)境變量和業(yè)務(wù)判斷圖文詳解
這篇文章主要給大家介紹了關(guān)于vue的index.html中獲取環(huán)境變量和業(yè)務(wù)判斷的相關(guān)資料,對(duì)vue來(lái)說(shuō)index.html是一個(gè)總的入口文件,vue是單頁(yè)面應(yīng)用,掛在id為app的div下然后動(dòng)態(tài)渲染路由模板,需要的朋友可以參考下2023-09-09
vscode中vue-cli項(xiàng)目es-lint的配置方法
本文主要介紹vscode中 vue項(xiàng)目es-lint的配置方法,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的的朋友參考下吧2018-07-07
VUE單頁(yè)面切換動(dòng)畫代碼(全網(wǎng)最好的切換效果)
今天小編就為大家分享一篇VUE單頁(yè)面切換動(dòng)畫代碼(全網(wǎng)最好的切換效果),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-10-10
Vue 實(shí)現(xiàn)樹(shù)形視圖數(shù)據(jù)功能
這篇文章主要介紹了Vue 實(shí)現(xiàn)樹(shù)形視圖數(shù)據(jù)功能,利用簡(jiǎn)單的樹(shù)形視圖實(shí)現(xiàn)的,在實(shí)現(xiàn)過(guò)程中熟悉了組件的遞歸使用,感興趣的朋友跟隨腳本之家小編一起學(xué)習(xí)吧2018-05-05
vue2.0設(shè)置proxyTable使用axios進(jìn)行跨域請(qǐng)求的方法
這篇文章主要介紹了vue2.0設(shè)置proxyTable使用axios進(jìn)行跨域請(qǐng)求,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-10-10
vuex(vue狀態(tài)管理)的特殊應(yīng)用案例分享
Vuex 是一個(gè)專為 Vue.js 應(yīng)用程序開(kāi)發(fā)的狀態(tài)管理模式。它采用集中式存儲(chǔ)管理應(yīng)用的所有組件的狀態(tài),并以相應(yīng)的規(guī)則保證狀態(tài)以一種可預(yù)測(cè)的方式發(fā)生變化。2020-03-03

