在 Vue3 中使用 Better-Scroll 实现滚动效果的步骤如下:
1. 安装依赖
npm install better-scroll
# 或
yarn add better-scroll
2. 基本使用
<template>
<div ref="wrapper" class="wrapper">
<div class="content">
<!-- 你的内容 -->
<div v-for="item in 100" :key="item">{{ item }}</div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted, onUnmounted, nextTick } from 'vue'
import BScroll from 'better-scroll'
const wrapper = ref(null)
let bs = null
onMounted(() => {
nextTick(() => {
bs = new BScroll(wrapper.value, {
probeType: 3, // 监听滚动事件
click: true // 启用点击
})
})
})
onUnmounted(() => {
if (bs) {
bs.destroy()
}
})
</script>
<style scoped>
.wrapper {
height: 400px; /* 必须指定高度 */
overflow: hidden; /* 关键样式 */
}
</style>
3. 处理动态内容
当内容异步加载时,需要手动刷新滚动实例:
<script setup>
import { watch } from 'vue'
// 假设有异步数据
const list = ref([])
fetchData().then(data => list.value = data)
watch(list, () => {
nextTick(() => {
bs?.refresh()
})
})
</script>
4. 常用配置选项
new BScroll(wrapper.value, {
scrollY: true, // 开启纵向滚动
scrollbar: true, // 显示滚动条
pullUpLoad: true, // 开启上拉加载
bounce: {
top: false, // 关闭顶部回弹
bottom: false // 关闭底部回弹
}
})
5. 事件监听
// 滚动事件
bs.on('scroll', (pos) => {
console.log(pos.x, pos.y)
})
// 上拉加载
bs.on('pullingUp', () => {
loadMoreData()
bs.finishPullUp() // 结束上拉
})
6. 注意事项
-
容器高度:外层容器必须设置固定高度且设置
overflow: hidden
-
DOM 层级:需要两层嵌套结构(wrapper > content)
-
初始化时机:确保在 DOM 渲染完成后初始化(使用 nextTick)
-
数据更新:内容变化后需要调用
bs.refresh()
-
销毁实例:组件卸载时调用
bs.destroy()
7. 完整示例(带下拉刷新)
<template>
<div ref="wrapper" class="wrapper">
<div class="content">
<div class="refresh-tip">下拉刷新</div>
<div v-for="item in list" :key="item">{{ item }}</div>
<div class="loading-tip">加载中...</div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted, onUnmounted, nextTick } from 'vue'
import BScroll from 'better-scroll'
const wrapper = ref(null)
const list = ref(Array.from({ length: 50 }, (_, i) => i + 1))
let bs = null
onMounted(() => {
nextTick(initScroll)
})
const initScroll = () => {
bs = new BScroll(wrapper.value, {
probeType: 3,
pullDownRefresh: {
threshold: 50,
stop: 30
}
})
// 下拉刷新
bs.on('pullingDown', async () => {
await refreshData()
bs.finishPullDown()
bs.refresh()
})
}
const refreshData = async () => {
// 模拟异步请求
return new Promise(resolve => {
setTimeout(() => {
list.value = Array.from({ length: 50 }, (_, i) => i + 1)
resolve()
}, 1000)
})
}
onUnmounted(() => {
bs?.destroy()
})
</script>
<style>
.wrapper {
height: 100vh;
overflow: hidden;
position: relative;
}
.refresh-tip,
.loading-tip {
text-align: center;
padding: 10px;
}
</style>
常见问题解决:
-
无法滚动:
-
检查容器高度是否设置
-
确认内容高度大于容器高度
-
查看是否缺少
overflow: hidden
-
-
点击失效:
-
在配置中设置
click: true
-
-
滚动卡顿:
-
添加 CSS 属性
transform: translateZ(0)
-
-
动态内容不更新:
-
在数据更新后调用
bs.refresh()
-
-
内存泄漏:
-
确保在组件销毁时调用
bs.destroy()
-
建议使用 @better-scroll/core 按需加载插件功能,保持项目体积最小化。