Vue2.x + Vant2.x + BetterScroll 封装滚动列表(上滑加载,下滑刷新)
Vant2.x 是一个轻量、可靠的移动端组件库,于 2017 年开源。
BetterScroll 是一款重点解决移动端(已支持 PC)各种滚动场景需求的插件。它的核心是借鉴的 iscroll (opens new window)的实现,它的 API 设计基本兼容 iscroll,在 iscroll 的基础上又扩展了一些 feature 以及做了一些性能优化。
一、全局安装vant,better-scroll
npm i vant batter-scroll -S
二、scroll-list.vue
<template>
<div ref="scrollRef">
<div class="scroll-content">
<slot></slot>
<div class="bot-loading">
<div v-if="isFinished">已经到底了...</div>
<van-loading v-else size="14px" >正在加载...</van-loading>
</div>
</div>
</div>
</template>
<script>
import { Loading } from 'vant'
import BScroll from 'better-scroll'
export default {
name: 'betterScroll',
components: {
[Loading.name]: Loading
},
props: {
/**
* 1 滚动的时候会派发scroll事件,会截流。
* 2 滚动的时候实时派发scroll事件,不会截流。
* 3 除了实时派发scroll事件,在swipe的情况下仍然能实时派发scroll事件
*/
scrollProbe: {
type: Number,
default: 1
},
openScroll: {
type: Boolean,
default: true
},
openPullUp: {
type: Boolean,
default: false
},
openPullDown: {
type: Boolean,
default: false
},
isFinished: {
type: Boolean,
default: true
},
// 滚动列表数据
scrollDataList: {
type: Array,
default: null
}
},
data () {
return {
scroll: null
}
},
methods: {
initScrollEffect () {
const scrollRef = this.$refs.scrollRef
if (!scrollRef) {
console.warn('未初始化DOM实例')
return false
}
const _bsScroll = this.scroll = new BScroll(scrollRef, {
click: true,
scrollY: true,
probeType: this.scrollProbe
})
if (this.openScroll) {
_bsScroll.on('scroll', (pos) => {
this.$emit('scrollEvents', pos)
})
}
// 是否派发滚动到底部事件,用于上拉加载
if (this.openPullUp) {
_bsScroll.on('scrollEnd', () => {
const {
y,
maxScrollY
} = _bsScroll
if (y <= (maxScrollY + 50)) {
this.$emit('pullUpEvents')
}
})
}
// 是否派发顶部下拉事件,用于下拉刷新
if (this.openPullDown) {
_bsScroll.on('touchEnd', (pos) => {
if (pos.y > 100) {
this.$emit('pullDownEvents')
}
})
}
},
scrollRefresh () {
this.scroll && this.scroll.refresh()
}
},
mounted () {
this.$nextTick(() => {
this.initScrollEffect()
})
},
watch: {
// 监听异步数据加载,重新计算高度,防止滚动失效
scrollDataList () {
setTimeout(() => {
this.scrollRefresh()
}, 100)
}
},
destroyed () {
if (this.scroll) {
this.scroll.destroy()
}
}
}
</script>
<style scoped lang="scss">
.scroll-content .bot-loading {
font-size: 12px;
padding: 15px 0;
color: $color-gray;
text-align: center;
}
</style>
三、注册全局组件
// plugin.js
import scrollList from '@/components/scroll/scroll-list.vue'
const publicComponent = {
install (vue) {
vue.component('scroll-list', scrollList)
}
}
export default publicComponent
// main.js
import publicComponent from '@/utils/plugin.js'
Vue.use(publicComponent)
四、引用组件
<template>
<scroll-list
class="scroll-list-box"
:open-pull-up="true"
:open-pull-down="true"
@pullDownEvents="getNoticeList"
@pullUpEvents="getNextPageHandle"
>
<ul>
<li></li>
</ul>
</scroll-list>
</template>
<script>
export default {
name: 'notice',
data () {
return {
isLoading: false,
isFinished: true,
finishEndText: '已经到底了...'
}
},
methods: {
getNoticeList () {
console.log('load-down')
},
getNextPageHandle () {
console.log('load-up')
}
}
}
</script>
本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。