如下
![](https://img-blog.csdnimg.cn/20210411150013169.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzM0NjEwNg==,size_16,color_FFFFFF,t_70)
- 我的遇到的问题是,有时候主页刚刚加载就直接就不能滚动,有时候滑动到中间,明明下面还有图片,就有滑不动了。在上拉加载更多时,图片是加载了,但是就是要等一下或者直接 不能向上滑动。
better-scroll 滚动原理
better-scroll它有两个div层,wrapper层 和 content层,wrapper 表示的是滑动区域,content表示的滚动内容,当content层的高度或宽度大于wrapper层的时候,就可以纵向滚动和横向滚动了(和游览器页面的滚动原理一样)
这里比我将的更清楚:
https://better-scroll.gitee.io/docs/zh-CN/guide/#%E6%BB%9A%E5%8A%A8%E5%8E%9F%E7%90%86
为什么不能滚动
上面说到,要在content高度或宽度大于 wrapper的高度或宽度的时候才可以滚动,高度宽度越大,滚动区域就越大。不能滚动的原因就是没有在content里面dom元素更新后 重新计算content的高度和宽度。所以解决思路就是在 content里面的dom元素加载后,调用 better-scroll 的refresh() 方法,重新计算高度和宽度。(说起来很简单,但也有很多要注意的地方)
具体解决方案
使用 observe-dom 配合 observe-image
他们本来就是 better-scroll的特性,只不过是为了让better-scroll更小,把很多特性都解耦了出来,成为了单独的插件,这样大家就可以按需进行安装了。
它可以自动监听content里面的dom的改变,然后调用refresh方法重新计算宽高。但是它有一个问题:它不能监听图片的加载完成,所以说 当你的content里面有很多图片的要展示的时候,还会出现 不能滚动的问题。那这怎么办呢?不用担心,在better-scroll2.1有 提供了一个新的插件,叫 observe-image,装上它就可以 监听图片的加载,然后重新计算宽度了。
怎么安装? 怎么使用?官网看 https://better-scroll.github.io/docs/zh-CN/plugins/observe-dom.html#%E5%AE%89%E8%A3%85
为什么要使用它们,它们的性能是否可靠?
- observe-dom 是基于
MutationObserver
接口实现的。这个接口是专门用来监听dom更改的。比如节点的更删、属性的变动、文本内容的变动、这个API都可以得到通知。它很接近事件它又与事件不同,事件的触发是同步触发,也就是dom变动会立即触发响应的响应函数(去排队执行);而MutationObserver
是异步触发,当dom改变事件不会马上触发,而是等到 一连串的改变都发生后,再去触发(很短的时间内只会触发一次)。比如你连续添加1000p
标签,最后MutationOberser
只会触发一次。这就很大程度节省了开销,优化了性能。而且observe-dom还针对频繁变动的 css样式,做了节流处理。 - observe-image 对图片的连续加载触发的refresh() 也做了节流处理。
为什么使用 observe-dom 不能监听 图片的加载完成?
因为observe-dom 基于 MutationObserve
接口实现。我查阅MDN 之后发现,这个接口只能监听: 子节点的变动(指新增,删除或者更改)、属性的变动、节点内容或节点文本的变动。并没有图片加载 监听 相关的描述。(图片 src属性被赋值,需要去建立连接去请求 图片资源)
补充
自己也可以 去监听图片的加载 并 对better-scroll的refresh函数 进行节流操作。
如下节流方法:(可参考)
function debounce(func, delay = 200) {
let timer = null;
return function(...args) {
if(timer) clearTimeout(timer);
timer = setTimeout(() => {
func.apply(this, args);
}, delay);
}
}