理了一理,H5开发遇到的那些兼容性问题

4,014 阅读4分钟

引言

这是笔者在过去开发H5应用时遇到的一系列兼容性问题,很多解决方式的原理并未阐述,只提供了解决问题的思路和技巧。希望帮助那些从事H5开发的同学减少解决兼容性问题的耗时。

1、ios禁用弹性滚动

问题描述

在这里插入图片描述

页面在没有设置滚动条或处于极限位置时,页面还是能跟随手指上下滑动。试想,如果我们开发的组件需要监听touch事件,例如:签名组件,那么弹簧效果会降低签名的体验。所以我们需要 根据具体的业务场景来禁用和启用弹簧效果

解决

使用inobounce ,根据业务场景手动打开和关闭弹簧效果。

iNoBounce.enable(); //开启
iNoBounce.disable(); //关闭
iNoBounce.isEnabled(); //是否可用

总共就3个api,还是比较简单的。

2、ios适配虚拟home键

问题描述

还是这张图:

在这里插入图片描述

如图所示,屏幕的下方有一个 黑色的横杠 (虚拟home键)。如果页面有底部菜单,这极其影响使用和美观。百度上可以搜索到一些解决方式,但是最简单最方便的方案才是我的首选。下列方案兼容性、难易程度尚可,推荐使用。

解决

设置html头部

<meta content="viewport-fit=cover" />

css中使用如下系统变量

为了兼容,需要同时使用 envconstant

padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);

3、ios纠正图片orientation

问题描述

之前曾开发过水印图片的功能,当时我们使用 canvas 来实现此功能:先将图片用cavas绘制;然后用canvas画出水印文字;最后再生成图片 (网上很多教程,这里不详细讲解了)。

但是,当使用ihpone 8及以上的机型上的企业微信app或者微信app(其他app可能会发生同样的问题,不是绝对的)进行拍照水印处理时,发现图片发生了旋转,其他机型正常。

在这里插入图片描述

为什么没有用jsapi去上传图片?因为很多第三方app,jsapi的上传图片功能会先将图片保存在第三方的文件服务当中,但是我们不希望发生这样的情况,我们希望把图片存在自己的文件服务当中,所以放弃jsapi上传图片。

解决

既然是机型的问题,那就针对机型做特殊处理好了:

  • iphone8及以上旋转图片
  • iphone8以下不做任何处理

获取机型要使用jsapi来获取,通过其他的“偏方”获取一点都不靠谱。

4、ios兼容popstate合并触发

问题描述

我们先来说下应用的实现,再来谈具体的问题,这样更容易理解一些。

下面是h5单页面应用模拟openWebview的图解。

在这里插入图片描述

  • 通过slide组件打开目标页面(其实是个组件,因为模拟的是openWebview,我们不妨称它为页面),同时为了记录历史,我们还需要调用history.pushState 来生成一个 假hash(只修改了hash部分,pathname没有修改)
  • 目标页面想要关闭当前页面时,会调用某个api执行 history.back() ,这样我们可以关闭当前页面(即当前slide组件)

具体的实现就是上述的情况,我们再来说说问题:

  • android: history.back() 连续执行n次,会 触发n次 popstate
  • ios: history.back() 连续 执行n次,只 触发1次 popstate

额~ 好吧~ 兼容!

解决

思路:记录 执行 history.back() 的总次数,仅在最后一次需要执行时通过 history.go() 跳跃式回退。这里需要用到事件防抖。

代码如下:

// 省略具体的实现
let hideSlides = []
Slide.prototype.hide = function () {
    this.comp.hide();//目标页面立即隐藏掉。后面的路由逻辑不管它。
    hideSlides.push(this);
    lazyHide();
}
lazyHide = debounce(() => {
    let hideIndex = hideSlides.length;
    if (!hideIndex) return;
    //执行到这一步,可以确定的是,需要移除那些slide了
    if (hideIndex === 1) {
        history.back();
    } else {
        history.go(-hideIndex);
    }
}, 50)

5、android避免软键盘遮挡光标

问题描述

安卓上,input输入框在获取焦点时会被唤起的软键盘遮盖。

在这里插入图片描述

我点的是手机1下方的一个字段,很明显,已经被软键盘遮挡,导致用户无法看到输入框。

解决

使用 scrollIntoView 方法

dom.onfocus = function() {
	if (isAndroid) {
		setTimeout(function(){    
	    	dom.scrollIntoView && dom.scrollIntoView(false);
	  	}, 1000)
	}
}

6、ios下iframe的各种问题

todo

7、移动端点击穿透和点击延迟

todo

有错误的地方,希望大家能够谅解和指正。

Peace And Love。