better-scroll这个组件不能说有多好,只能说可以拿来用用。但是很多人都碰到了引入这个组件以后,页面反而不能滚动的问题。今天我就来谈谈怎么彻底解决这个问题
首先要谈谈better-scroll页面滚动的原理:
如上图所示,只有当内容高度大于父级容器的高度时,页面才能滚动!
这是滚动的核心原理!
所以父级容器高度必须是固定的!如果父级容器的高度不固定,是动态的,那么内容高度是没法大于父级容器高度的,此时页面没法滚动
有人说这不是废话吗,是的。这看起来的确像是废话,但是你要知道:
在现实环境中:由于dom的渲染需要请求网络数据,而且ajax请求需要时间,而better-scroll的初始化又是异步的,也就是说better-scroll不会等待dom渲染完毕才计算出dom的高度!
注意:这里是关键!
所以: 由于异步的原因,better-scroll计算出的初始dom高度有可能是不正确的!
因为高度计算不正确,内容高度没有超过父容器高度,此时hasVerticalScroll属性就是false!
此时页面当然不能滚动!
所以这里有两种解决办法:
1. 每当发生页面拖动的时候,重新refresh better-scroll的实例
import BScroll from "@better-scroll/core";
import myPullUp from "@better-scroll/pull-up";
BScroll.use(myPullUp);
this.scroll = new BScroll(this.$refs.wrapper, {
probeType: this.probeType,
click: true,
pullUpLoad: true,
});
this.scroll.on("pullingUp", () => { // 每当页面上下拖动时,刷新scroll实例
this.scroll.refresh();
});
2. watch动态监视scroll组件收到的异步数据,一旦发现更新就better-scroll的实例
// dataInfo是scroll组件从父组件接收到的异步数据
this.$watch("dataInfo", (newVal, oldVal) => {
if (newVal.length > 0) {
this.$nextTick(() => {
this.scroll.refresh();
});
}
});
采用以上两种方法(二选一)以后:
hasVerticalScroll就变成了true
注意:不要使用better-scroll官网推荐的setTimeout方法,因为这种方法太过愚蠢!你这个延迟时间设置多少合适呢,靠猜?!delay写死了,显得代码非常不优雅,我始终认为,在js中使用setTimeout处理dom的都是蠢货!
但是这还不够!!
很多人做到了这一步还是没法滚动!
所以,我在这里介绍终极解决办法:
你们有没有发现:你们都是从pc页面切换到移动端页面的,这个就是关键!
如果是这样就肯定不能滚动!因为在移动端这边,scroll对象还没有完成初始化!也不能正确计算高度,因为你是从pc端切换到移动端的。
终极解决办法:你必须始终在移动端刷新页面,这样scroll就能正确完成初始化,正确加载dom,正确计算dom高度。
你学废了吗!