目录
4.1 Vue2 中,初始化 better-scroll 的注意事项
1. batter-scroll 原理
- wrapper 是父容器,它会有固定的高度;
- 父容器的第一个子元素为 content,它的高度会随着内容的大小而撑高;
- 当 content 的高度不超过 wrapper 的高度,是不能滚动的;
- 当 content 的高度超过了 wrapper 的高度,就可以滚动 content 了;
2. 初始化 batter-scroll 的正确姿势
<div class="wrapper"> <ul class="content"> <li>...</li> ... </ul> </div> // 初始化 better-scroll import BScroll from 'better-scroll' let wrapper = document.querySelector('.wrapper') // 后面添加了插件配置项对象 let scroll = new BScroll(wrapper, {})
3. better-scroll 注意事项
- 初始化时机,初始化时,会计算父元素和子元素的高度和宽度,来决定是否可以滚动;因此,初始化 better-scroll 时,必须确保父元素和子元素的内容已经正确渲染了
- 如果子元素或者父元素 DOM 结构发生改变,必须重新调用 scroll.refresh() 方法重新计算,来确保滚动效果的正常
4. 在 Vue2 中使用 better-scroll
4.1 Vue2 中,初始化 better-scroll 的注意事项
- 在 mounted 函数中执行 better-scroll 初始化,此时 wrapper 的 DOM 已经渲染了
- 在 $nextTick 函数回调中执行 better-scroll 初始化,因为 better-scroll 依赖随数据变化而变化的 DOM
- this.$refs.wrapper 用于获取父元素 DOM
初始化的小技巧:把 this.$nextTick 替换成 setTimeout(fn, 20) 也是可以的(20 ms 是一个经验值,每一个 Tick 约为 17 ms)
Vue2 中,初始化 better-scroll 的示例代码:<template> <div class="wrapper" ref="wrapper"> <ul class="content"> <li>...</li> ... </ul> </div> </template> <script> import BScroll from 'better-scroll' export default { mounted() { this.$nextTick(() => { this.scroll = new Bscroll(this.$refs.wrapper, {}) }) } } </script>
4.2 better-scroll 请求异步数据
- Vue 数据发生变化(this.data = res.data)到 页面重新渲染 是一个异步的过程
- 初始化 better-scroll 要在 DOM 重新渲染后,也就是获取数据之后
- 获取数据之后,数据就发生了变化,会让 dom也发生变化,而滚动条依赖于变化之后的 dom 元素,所以这里用到了 this.$nextTick 包裹初始化 better-scroll 代码,当然替换成 setTimeout(fn, 20) 也是可以的
<template> <div class="wrapper" ref="wrapper"> <ul class="content"> <li v-for="item in data">{{ item }}</li> </ul> </div> </template> <script> import BScroll from 'better-scroll' export default { data() { return { data: [] } }, created() { requestData().then((res) => { this.data = res.data this.$nextTick(() => { this.scroll = new Bscroll(this.$refs.wrapper, {}) }) }) } } </script>
几点解释:- 异步请求数据在 created() 里进行,而不是放到 mounted() 的原因?
- ① 异步请求数据是异步的过程,①执行完之后,没拿到数据的 dom 早就渲染好了;② 数据改变重新渲染 dom 也是异步的过程,所以异步拿到数据之后,再异步初始化 better-scroll
4.3 better-scroll 的封装
- html 结构部分的封装:
- better-scroll 只需考虑父元素,内部多少层都没关系
- 所以除了父元素,其他地方放插槽就行
js 逻辑部分的封装:- 通过 props ,把对 better-scroll 定制化的控制权,交给父组件
- 通过 methods,代理 better-scroll 的方法
- 通过 watch,监听传入的 data,data 改变,就 refresh
加延时 refresh 的原因:如果给列表加了动画效果,那么 dom 渲染完成是动画完成之后<template> <div ref="wrapper"> <slot></slot> </div> </template> <script> import BScroll from "better-scroll"; export default { props: { /** * 1 滚动的时候会派发 scroll事件,会截流。 * 2 滚动的时候实时派发 scroll事件,不会截流。 * 3 除了实时派发 scroll事件,在 swipe 的情况下仍然能实时派发 scroll事件 */ probeType: { type: Number, default: 1, }, /** * 点击列表是否派发 click事件 */ click: { type: Boolean, default: true, }, /** * 是否开启横向滚动 */ scrollX: { type: Boolean, default: false, }, /** * 是否派发滚动事件 */ listenScroll: { type: Boolean, default: false, }, /** * 列表的数据 */ data: { type: Array, default: null, }, /** * 是否派发滚动到底部的事件,用于上拉加载 */ pullup: { type: Boolean, default: false, }, /** * 是否派发顶部下拉的事件,用于下拉刷新 */ pulldown: { type: Boolean, default: false, }, /** * 是否派发列表滚动开始的事件 */ beforeScroll: { type: Boolean, default: false, }, /** * 当数据更新后,刷新scroll的延时 */ refreshDelay: { type: Number, default: 20, }, }, mounted() { // 保证在DOM渲染完毕后,初始化 better-scroll setTimeout(() => { this._initScroll(); }, 20); // 模拟了点击速度 17ms 也可放入 nextTick }, methods: { // 初始化 better-scroll _initScroll() { if (!this.$refs.wrapper) { return; } // 配置 better-scroll this.scroll = new BScroll(this.$refs.wrapper, { probeType: this.probeType, // 何时派发 scroll事件 click: this.click, // 点击列表是否派发 scrollX: this.scrollX, // 是否开启横向滚动 }); // 是否派发滚动事件 if (this.listenScroll) { this.scroll.on("scroll", (pos) => { this.$emit("scroll", pos); }); } // 是否派发滚动到底部事件,用于上拉加载 if (this.pullup) { this.scroll.on("scrollEnd", () => { // 滚动到底部 if (this.scroll.y <= this.scroll.maxScrollY + 50) { this.$emit("scrollToEnd"); } }); } // 是否派发顶部下拉事件,用于下拉刷新 if (this.pulldown) { this.scroll.on("touchend", (pos) => { // 下拉动作 if (pos.y > 50) { this.$emit("pulldown"); } }); } // 是否派发列表滚动开始的事件 if (this.beforeScroll) { this.scroll.on("beforeScrollStart", () => { this.$emit("beforeScroll"); }); } }, disable() { // 代理 better-scroll 的 disable 方法 this.scroll && this.scroll.disable(); }, enable() { // 代理 better-scroll 的 enable 方法 this.scroll && this.scroll.enable(); }, refresh() { // 代理 better-scroll 的 refresh 方法 this.scroll && this.scroll.refresh(); }, scrollTo() { // 代理 better-scroll 的 scrollTo 方法 this.scroll && this.scroll.scrollTo.apply(this.scroll, arguments); }, scrollToElement() { // 代理 better-scroll 的 scrollToElement 方法 this.scroll && this.scroll.scrollToElement.apply(this.scroll, arguments); }, }, watch: { // 延时 refreshDelay 时间后调用refresh方法重新计算,保证滚动效果正常 data() { setTimeout(() => { this.refresh(); }, this.refreshDelay); }, }, }; </script>
4.4 better-scroll 上拉加载下拉刷新
- 下拉加载、上拉刷新,可以 动态更新 列表中的数据
- 下面用 下拉加载 作为例子:
- 父组件需要把数据 data 通过 prop 传给 scroll 组件
- 实现下拉刷新,只需要通过 prop 把 pulldown 设置为 true;并且监听 pulldown 的事件,去做一些 获取并更新数据 的动作
<template> <!-- 假设已经全局注册 scroll 组件 --> <scroll class="wrapper" :data="data" :pulldown="pulldown" @pulldown="loadData" > <ul class="content"> <li v-for="item in data">{{item}}</li> </ul> <div class="loading-wrapper"></div> </scroll> </template> <script> import BScroll from "better-scroll"; export default { data() { return { // 列表数据 data: [], // 是否派发顶部下拉的事件,用于下拉加载 pulldown: true, }; }, created() { this.loadData(); }, methods: { // 重新拼接获取的列表数据 loadData() { requestData().then((res) => { this.data = res.data.concat(this.data); }); }, }, }; </script>
Vue2 封装 better-scroll 插件,实现顺滑的滚动效果
最新推荐文章于 2024-07-29 11:08:22 发布
本文详细介绍了Better-Scroll的原理,初始化步骤,注意事项,以及在Vue2中的应用。重点讲解了在Vue组件中如何正确初始化和更新Better-Scroll,包括在数据异步加载后初始化,以及封装Better-Scroll组件的方法。同时,提到了上拉加载和下拉刷新的实现方式,强调了在数据变化后刷新滚动效果的重要性。
摘要由CSDN通过智能技术生成