最近ios发布新版本系统12.1,随着部分用户的系统更新,一些问题也渐渐暴露出来。。。ios
我当时就是一惊,通常出如今事件上的问题都是疑难杂症。况且是跟键盘相关的。浏览器
咱们都知道在H5端是无法监控键盘的弹出与收起的,resize事件触发的机型极其有限,况且我在ios中实测没有触发,安卓反而能够。由于安卓弹起键盘时会修改视窗的大小,可是ios并不会,若是你在ios上设置一个100%高度的body,弹起键盘后你会发现这个body是能够上下滚动的,即100%高度的body超出了视窗。bash
(PS: iphoneX的测试机被拿走了,这是安卓下模拟的ios表现😭,总之ios能滚成这样)
微信
下图是一个问题描述,当咱们弹起键盘,而且使用以下的布局时: app
body高度是100%,modal使用fixed定位,四个方向设置为0,预期的结果应该是二者都适应窗口大小,弹起键盘时自动适应。安卓上与预期相同,ios打开后出现整个modal和body能够滑动的状况。iphone
ios上一直有个很🐂的优化,弹出键盘时会自动把当前输入框滚动到可视区域,在安卓中会出现键盘遮挡输入框的问题,须要手动调整,ios扳回一城👏👏。我在项目中为了让安卓达到一样的效果也是死了很多脑细胞。布局
可是!!项目自己在稳定运行半年的状况下,此次开始出现问题了。。。测试
在ios 12.1 中,机型为iphoneX,当咱们聚焦输入框弹出虚拟键盘,而后点击键盘收起。出现了以下的效果图,而且下半部分作点击事件无效。优化
从现象中找问题,在虚拟键盘被收起的状况下,能够看到modal框视图正常得弹回了,可是仔细看看透明区域下,body视图还处在键盘弹起时的状态。what fuck? 而后modal下面的可操做区域始终点击无效。。。。ui
推测是body没有正确从新渲染,致使点击事件不处于body内而没法触发。
(简陋推测图......)
那么怎么解决呢,是否是只要把body‘推’会来就好了? 方向有了,如今是如何‘推’的问题。
上文有说过,ios下弹出/收起键盘是没有触发resize事件的,那么在什么节点触发‘推’的操做就成了问题。
这时候封装的好处就体现出来了,由于项目中全部的地方都是使用封装过的input框,因此只须要在封装中作改造就行了。ios中点击虚拟键盘的完成按钮会触发失焦事件,安卓却不会,正是咱们须要的钩子。
在钩子中设置“推回”:
onBlur = (e) => {
const { onBlur } = this.props;
document.body && (document.body.scrollTop = 0);
onBlur && onBlur(e);
}
复制代码
问题初步解决,可是引起的新问题也很明显,任何onBlur事件都会作出 scrollTop = 0 的操做,严重影响体验。
继续经过现象思考问题,当咱们使用滑动触摸事件的时候,body会“跳动”到正常位置,而不不是正常的滚动,这一点很重要!
这代表了浏览器作了一个错误的渲染,那我不由想到,咱们作的“推”的操做是否必须?在一个错误的渲染下,咱们是否只须要在键盘收起后作一个触发“重绘”的操做。
问题解决了,最终解决方案就很明显:
onBlur = (e) => {
const { onBlur } = this.props;
document.body && (document.body.scrollTop = document.body.scrollTop);
onBlur && onBlur(e);
}
复制代码
在input输入框失去焦点的钩子中设置滚动到原有位置(document.body.scrollTop = document.body.scrollTop)
,触发浏览器的重绘,使的错误的渲染回复正常,滚动位置也不会有改变,没有影响体验。
是否是很简单?
解决方案的简单,是创建在深层的思考中的,若是这篇文章能对你有所触动,那个人写做就没有白费。
(绝望的是我出现bug时去搜索这个问题居然没有找到可用答案😂😂)
/**
* 处理iOS 微信客户端6.7.4 键盘收起页面未下移bug
*/
;(/iphone|ipod|ipad/i.test(navigator.appVersion)) && document.addEventListener('blur', (e) => {
// 这里加了个类型判断,由于a等元素也会触发blur事件
['input', 'textarea'].includes(e.target.localName) && document.body.scrollIntoView(false)
}, true)
复制代码
— The End