背景

iOS内嵌H5页面有一个默认的弹簧效果,即整个页面可以被上下拖拽滚动
弹簧效果视频
但并非所有场景都希望有这个效果的,本篇主要用于记录如何使其被禁用

正统做法

这种处理WebView容器默认效果最正统的方式,当然是让容器自己来提供Bridge开关,互联网Hybrid应用碰到类似问题通常也都是这么解决的。不过很可惜我们这边并没有Native开发,Bridge SDK也不支持任何自定义扩展,所以只能用H5范围内的野路子来处理了

禁用滚动

这个问题网上一搜其实有不少人都贴了自己的代码,思路都是通过禁用超出边界的滚动来实现的,不过我沾了几个伙计的代码后发现并不好使,要不就是压根不生效,要不就是页面内部原本可以上下滑动的区域也动不了了,毕竟好使的话我也犯不着写一篇网上一艘就有的解决方案了
网上代码不好使,但我也懒得自己写,虽说这个实现的大思路是比较明确的,但要写的话考虑的东西也不少,费心费力费时间。那有没有合适的库已经做过这个事了呢?

GitHub拯救世界

不知道是哪里使用的不对,github上有的库用起来也有问题,费了半天劲总算我找到了一个好使的https://github.com/lazd/iNoBo...,这个库支持script标签引入,老项目也能用
具体使用方式如下:

  1. 尽早引入inobounce.min.js,之后window上就会挂载iNoBounce属性
  2. 在一个合适的时机调用window.iNoBounce.enable(),这个时机是指页面已经完全渲染出来,但单纯在跟页面的mounted使用发现有一些问题,会让页面整体错位,我在mounted里又延迟了500毫秒后才正常,最终代码为

    // App.vue
    mounted () {
     setTimeout(() => {
       // 如果是iOS,则禁用弹簧效果
       this.disableBounce();
     }, 500);
    },
    
    disableBounce () {
     if (isIOS() && window.iNoBounce) {
         window.iNoBounce.enable();
     }
    }

    这么一搞iOS内嵌H5就顺眼多了,整体感官和安卓就统一起来,少了页面的轻浮感。但事情到这里还没有结束

后来发现的问题

这个禁用弹簧功能上线后,我们的异常监控陆陆续续收到一些JS报错信息

// 错误信息
TypeError: Argument 1 ('element') to Window.getComputedStyle must be an instance of Element

getComputedStyle方法的入参有问题,在排查后发现是这个库里报出来的,inobounce.min.js格式化后的具体位置如下

可以看到这个el的来源是事件入参event的target属性,这个玩意普遍认知上也不应该出现空或者非Element对象,我们的测试机也没能本地复现这个问题,怀疑可能是一些特定机型或场景才会出现
虽然没有搞清楚el到底还能是什么,不过解决方案倒是非常简单,增加健壮性逻辑即可,将while那一行的条件修改后就没有再统计到JS异常了

el !== document.body && el !== document && el && el.nodeType === 1

魔芋药丸
15 声望0 粉丝