最近使用BetterScroll比较多,记录下中途踩的坑
BetterScroll官网地址:better-scroll.github.io/docs/zh-CN/…
github社区:github.com/ustbhuangyi…
一、添加scroll后,页面滚不动
我们先了解下页面的滚动原理。只有当内容区域content溢出容器wrapper,即content高度大于wrapper,且wrapper设置了overflow:hidden后,页面才会形成滚动条。
所以先检查下自己代码中的元素的高度是否设置正确,内容高度>容器高度
其次,如果页面的数据是动态从接口请求回来的,那拿到数据后,需要调scroll的refresh()方法,重新计算BetterScroll,否则也会出现无法滚动的情况。
对于页面有图片展示的,如果图片初始高度不是固定的,那一定要在图片渲染完后,拿到最新的图片高度后,再调refresh()方法刷新(这个地方踩了好几次坑...)。
vue中可以使用以下方式,@load事件会在图片加载完成后触发
<img :src="showImage" @load="imgLoad" />
methods: {
imgLoad() {
console.log("资源加载完毕执行");
this.$refs.scroll.refresh();
},
},
总结来说页面滚不动有以下3个可能:
- 内容高度和容器高度设置有误,不满足滚动条件
- 数据异步请求后,未重新计算滚动高度
- 页面有自适应高度的图片,图片渲染完后,高度变化,未重新计算
二、添加scroll后,页面横向滚动失效
scroll只支持一个方向的滚动,如果未设置scrollX和scrollY的话,默认为纵向,那页面原生的横向滚动(比如左右滑动)则被禁止,希望保留的话,需要用到eventPassthrough属性。eventPassthrough为 horizontal,保留横向的原生滚动,为vertical,保留纵向的原生滚动。
需要注意官网的这句话,小心使用这个API。
经实战测试,eventPassthrough设置为 horizontal-保留横向的原生滚动,页面的纵向滚动会受到影响,比如在微信打开页面往下滚动时,偶尔会把整个webview的页面拖下来,可以看到“网页由xxx提供”这段文字,而不是在我们页面里面的某个容器上下滚动,这就导致页面滑动有种卡顿的效果,但好像只在安卓上会出现。(看源码貌似eventPassthrough不为空时,页面的touch事件被开启了)
解决方案:在自己的页面中监听touch事件,判断手指滚动方向,若为上下滑动,调用e.preventDefault(),阻止原生的滚动(注意离开页面前,要移除监听)。
三、嵌套div,触发多次clik事件
场景: scroll的click属性设置为true,页面纵向scroll中又嵌套了一个左右滚动的楼层,也是一个scroll,点击楼层,触发了两次click事件。
原因是scroll组件里,在touch事件中调用了e.preventDefault(),阻止了click事件执行,所有事件都由BetterScroll内部来管理,click配置项设置为true,即可派发事件,那嵌套的话,相应的也就会被派发两次。
官网提供了两种解决方案:
let innerBS = new BScroll('.wrapper', {
stopPropagation: true, // 方案一:阻止事件冒泡,经测试,该方案会导致手指在内层scroll区域做上下滚动时无反应,不太可行
})
// 或者
let innerBS = new BScroll('.wrapper', {
click: false, // 方案二:阻止内层scroll的click事件派发,经测试,该方案可行
})
四、scroll中的图片不支持长按识别
前面讲到BetterScroll中调用了e.preventDefault(),阻止了原生的滚动,也阻止了原生组件的默认行为,比如长按复制、图片长按识别等。
经过一番查找,找到了这个属性preventDefaultException,如果不配置的话,只有input、textarea、button、select、audio 这些标签的默认行为不会被阻止。
要支持图片的话,增加img标签设置:
preventDefaultException:{ tagName: /^(INPUT|TEXTAREA|BUTTON|SELECT|AUDIO|IMG)$/}; // 加上img标签
五、从上一页返回,偶现未停留在原先滚动位置,而是回到顶部
此问题暂未找到具体原因,项目中用的是1.0版本的,升级到2.0后问题修复。
六、click设置true,但在pc端点击事件仍无效
踩过上面的坑后,在移动端,终于达到了理想的效果,但是又发现pc端点击无反应,经过排查,click需要设置为false:
function isMobile() {
const ua = navigator.userAgent.toLowerCase();
return /mobile|android|iphone|ipod|phone|ipad/i.test(ua);
}
let scroll = new BScroll('.wrapper', {
click: isMobile(),// 移动端设置为true,pc端为false
});