兼容性问题记录
2023-06-08 00:51:28 # fontend

1. Android 上底部样式有 absolute/fix 定位的时候,软键盘弹起时会顶起底部固定的 div

部分 android 手机确实会这样,软键盘弹起直接改变了窗口的尺寸大小,所以底部按钮看起来就是被顶起来的样子。解决方案就是识别是 android 客户端,onresize 监听窗口尺寸发生变化时让底部 div 消失,收起时底部 div 出现。

1
2
3
4
5
6
7
8
9
10
11
12
13
const isAndroid = /Android|Adr/i.test(window.navigator.userAgent);
const originalHeight = document.documentElement.clientHeight || document.body.clientHeight;

if (isAndroid) {
window.onresize = () => {
const resizeHeight = document.documentElement.clientHeight || document.body.clientHeight;
if (resizeHeight < originalHeight) {
this.setState({ showBottomBar: false });
} else {
this.setState({ showBottomBar: true });
}
};
}

2. safari 中 input 输入框强制自带圆角边框

1
border-radius: 0

3. safari 中 input 输入框 focus 时,页面会强制自动放大,并且失焦之后并不会缩回去。

这是因为 safari 和 android 在移动端自适应宽度上的处理方式不同导致的, safari 认为 focus 输入框时就应该让其放大,方便用户输入,但是失焦的时候,又不自动缩回去,不知道几个意思,导致咱们的 qa 认为这是个 bug。所以为了保持一致,需要把 safari 的这一行为禁用掉。

1
2
// 禁止页面放大缩小的功能
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />

4. safari 中对 css: -webkit-mask-image 不支持,图片无法加载

-webkit-mask-image 中的 url 在 safari 上加载时显示不出来,控制台有报错。可以使用 -webkit-mask-box-image 替换,亲测有效。

5. Android 的不同机型 svg element.getBoundingClientRect 获取的位置不一样,导致无法根据其返回的位置信息显示 UI

我们的项目里 android 需要兼容到 android 5,chrome 的话最低兼容版本是 52, 而 android 上不同版本的 webview 内核不同的手机厂商下是不固定的,所以 chrome 的版本也是不固定的。

这个问题其实是 chrome 指定版本的问题,测试发现在 83 上会出现点击节点的时候通过getBoundingClientRect 获取的位置是被放大了,并且是根据 dpi 放大的,通过 caniuse 中确认 chrome 支持是没问题的,但是 issues 里面有相关的 Chromium issue #47998. 然而这个 bug 应该在 2013 年就被修复了,然后对比 chrome 的发布列表 83版本是2020年发布的,但是确实还是有问题,然后试了下 78 版本的也有这个问题。还是不知道为啥位置会不准,但是根据 dpi 缩小就可以了。所以目前的解决方案是判断 chrome 的版本,如果是在78-83区间的版本,获取的 x, y, top, left 相应属性值就会根据 dpi 缩小。

6. 移动端的点击穿透问题

移动端上支持响应 touch 和 click 事件,touch 事件总是先触发,大概 300ms 之后 click 会触发,click 事件触发之前,如果该绑定元素消失了,就会触发该元素下面的元素上。这种情况一般出现在弹窗和点击弹窗立马消失,弹窗下方又刚好有 click 原生事件的元素的情况下,一般是建议移动端点击事件全部使用 touch 代替 click,最好不要在一个元素上同时绑定 touch 和 click。如果出现这样的情况,可以在 touch 执行完毕的时候 e.preventDefault 可以解决。