BetterScroll踩坑分享

1,777 阅读1分钟

最近使用BetterScroll比较多,记录下中途踩的坑

BetterScroll官网地址:better-scroll.github.io/docs/zh-CN/…

github社区:github.com/ustbhuangyi…

一、添加scroll后,页面滚不动

我们先了解下页面的滚动原理。只有当内容区域content溢出容器wrapper,即content高度大于wrapper,且wrapper设置了overflow:hidden后,页面才会形成滚动条。

image.png

所以先检查下自己代码中的元素的高度是否设置正确,内容高度>容器高度

其次,如果页面的数据是动态从接口请求回来的,那拿到数据后,需要调scroll的refresh()方法,重新计算BetterScroll,否则也会出现无法滚动的情况。

对于页面有图片展示的,如果图片初始高度不是固定的,那一定要在图片渲染完后,拿到最新的图片高度后,再调refresh()方法刷新(这个地方踩了好几次坑...)。

vue中可以使用以下方式,@load事件会在图片加载完成后触发

  <img :src="showImage" @load="imgLoad" />
  methods: {
    imgLoad() {
      console.log("资源加载完毕执行");
      this.$refs.scroll.refresh();
    },
  },

总结来说页面滚不动有以下3个可能:

  • 内容高度和容器高度设置有误,不满足滚动条件
  • 数据异步请求后,未重新计算滚动高度
  • 页面有自适应高度的图片,图片渲染完后,高度变化,未重新计算

二、添加scroll后,页面横向滚动失效

scroll只支持一个方向的滚动,如果未设置scrollXscrollY的话,默认为纵向,那页面原生的横向滚动(比如左右滑动)则被禁止,希望保留的话,需要用到eventPassthrough属性。eventPassthrough为 horizontal,保留横向的原生滚动,为vertical,保留纵向的原生滚动。

需要注意官网的这句话,小心使用这个API。

截屏2022-11-05 17.43.19.png

经实战测试,eventPassthrough设置为 horizontal-保留横向的原生滚动,页面的纵向滚动会受到影响,比如在微信打开页面往下滚动时,偶尔会把整个webview的页面拖下来,可以看到“网页由xxx提供”这段文字,而不是在我们页面里面的某个容器上下滚动,这就导致页面滑动有种卡顿的效果,但好像只在安卓上会出现。(看源码貌似eventPassthrough不为空时,页面的touch事件被开启了)

解决方案:在自己的页面中监听touch事件,判断手指滚动方向,若为上下滑动,调用e.preventDefault(),阻止原生的滚动(注意离开页面前,要移除监听)。

image.png

三、嵌套div,触发多次clik事件

场景: scroll的click属性设置为true,页面纵向scroll中又嵌套了一个左右滚动的楼层,也是一个scroll,点击楼层,触发了两次click事件。

原因是scroll组件里,在touch事件中调用了e.preventDefault(),阻止了click事件执行,所有事件都由BetterScroll内部来管理,click配置项设置为true,即可派发事件,那嵌套的话,相应的也就会被派发两次。

image.png

官网提供了两种解决方案:

let innerBS = new BScroll('.wrapper', {
  stopPropagation: true, // 方案一:阻止事件冒泡,经测试,该方案会导致手指在内层scroll区域做上下滚动时无反应,不太可行
})

// 或者
let innerBS = new BScroll('.wrapper', {
  click: false//  方案二:阻止内层scroll的click事件派发,经测试,该方案可行
})

四、scroll中的图片不支持长按识别

前面讲到BetterScroll中调用了e.preventDefault(),阻止了原生的滚动,也阻止了原生组件的默认行为,比如长按复制、图片长按识别等。

经过一番查找,找到了这个属性preventDefaultException,如果不配置的话,只有inputtextareabuttonselectaudio 这些标签的默认行为不会被阻止。

image.png

要支持图片的话,增加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
});