betterScroll在MVVM框架中使用时最麻烦的是更新时机,一般的需要滚动的列表数据都是来源于后端,是异步的。就必须要渲染完后refresh()一下。但是单独的Scroll组件是通过插槽放置列表数据内容的,无法直接确定什么时候更新了节点。通过插槽放置内容,当内容加载完成就更新betterScroll实例,这里就涉及到父子传递,这里使用了依赖注入的办法把refresh()传递到子组件中
- 新建一个page.vue组件 betterScroll需要的基本结构
点击查看代码
<!-- page.vue -->
<template>
<div class="page">
<div class="center">
<slot></slot>
</div>
</div>
</template>
<script setup lang='ts'>
</script>
<style lang="less" >
.page {
width: 100%;
height: 100%;
min-width: fit-content;
max-width: 100vw;
overflow: hidden;
.center {
height: auto;
}
}
</style>
- 新建use-scroll.ts
scrollRef是要监听滚动的DOM 在这里声明后把它传出到组件绑定到ref
bs放置BScroll实例
在getScroll方法中new BScroll,如果已经new过了就直接更新原来的bs实例
更新时需要在等待DOM更新完成也就是放在nextTick之后
//use-scroll.ts
import type { Options } from '@better-scroll/core';
import BScroll from '@better-scroll/core';
import MouseWheel from '@better-scroll/mouse-wheel';
import ScrollBar from '@better-scroll/scroll-bar';
import { nextTick, onMounted, onUnmounted, ref } from 'vue';
BScroll.use(MouseWheel)//鼠标滚轮
BScroll.use(ScrollBar)//滚动条
/**
* BScroll 滚动
* @param { Options } options BScroll配置项
* @returns { {scrollRef,bs,getScroll} }
*/
export default (options?: Options) => {
const scrollRef = ref<HTMLElement>()
const bs = ref<BScroll | undefined>()
//new BScroll 如果new过了就直接更新
const getScroll = async () => {
if (!scrollRef.value) return
if (!bs.value) {
// BetterScroll实例
bs.value = new BScroll(scrollRef.value, {
scrollY: true,//沿Y轴滚动
scrollX: true,//沿X轴滚动
click: true,//派发点击事件
probeType: 3,//反向偏移量
mouseWheel: true,//开启鼠标滚轮插件
scrollbar: true,//开启滚动条插件
...(options || {})
})
return
}
await nextTick()
// bs.scrollToElement(scrollRef.value, 0, true, true)
bs.value.refresh()//更新BScroll
}
onMounted(() => {
getScroll()
})
onUnmounted(() => {
// 移除BetterScroll
bs.value && bs.value.destroy && bs.value.destroy?.()
})
return {
scrollRef,//所监听的ref
bs, //BetterScroll实例
getScroll,//重新计算scroll
}
}
修改page.vue组件
引入use-scroll.ts 把scrollRef绑定到外层节点上
添加依赖注入 把getScroll提供给子组件 provide('scroll', getScroll)
<template>
<div class="page" ref="scrollRef">
<div class="center">
<slot></slot>
</div>
</div>
</template>
<script setup lang='ts'>
import scroll from './use-scroll';
const { scrollRef, getScroll, bs } = scroll()//使用BetterScroll
// 注入更新BScroll方法 子组件在节点变化后调用
provide('scroll', getScroll)
</script>
<style lang="less" >
.page {
width: 100%;
height: 100%;
min-width: fit-content;
max-width: 100vw;
overflow: hidden;
.center {
height: auto;
}
}
</style>
新建一个list.vue 渲染20张图片列表
<template>
<ul>
<li v-for="item in data.list">
<img style="width:100%" :src="item.img" alt="">
</li>
</ul>
</template>
<script setup lang='ts'>
import { onMounted, reactive } from 'vue';
const getScroll = inject<Function>('scroll', () => { })//接收getScroll
const data = reactive<{ list: { img: string }[] }>({
list: []
})
onMounted(() => {
// 5秒后更新数据并调用getScroll重新计算
setTimeout(() => {
data.list = Array(20).fill({ img: 'data:image/jpeg;base64,/9j/.....' })//20张图片
getScroll()
}, 5000)
})
</script>
引入到App.vue中使用
<script setup lang="ts">
import list from './views/pages/list.vue';
import page from './components/pageView/page.vue';
</script>
<template>
<page class="main">
<list />
</page>
</template>
<style scoped>
.main {
width: 100vw;
height: 100vh;
}
</style>
标签:scrollRef,betterScroll,bs,vue3,import,BScroll,scroll,getScroll
From: https://www.cnblogs.com/zsyh/p/17072337.html