H5兼容问题及解决办法小记

878 阅读3分钟

笔者最近开发完一个H5项目,在浏览器的模拟器中表现完美,可谁知到测试阶段,真机上却是漏洞百出。踩了许多的坑,于是痛定思痛,写下一篇文章来记录这些问题,与大家分享。

1. IOS高版本软键盘收回后,页面不会回到原位

在高版本的苹果手机上,软键盘弹出会使被遮盖的表单上移,但是软键盘收起却不能复原,这导致页面的焦点错乱,尤其在页面上有弹出层的时候。

这就需要在键盘收起后手动将页面复原

const isRest = false
document.body.addEventListener("focusin", () => {
    //软键盘弹出的事件处理
    isReset = false;
});
document.body.addEventListener("focusout", () => {
    //软键盘收起的事件处理
    isReset = true;
    setTimeout(() => {
    //当焦点在弹出层的输入框之间切换时先不归位
    if (isReset) {
        const bfscrolltop = document.body.scrollTop;
        document.body.scrollTop = bfscrolltop;
        }
    }, 100);
});

2. 安卓点击软键盘确认键后无法使input焦点移出

因为笔者对表单的校验采用的是blur方式,但是在安卓机上点击软键盘确认按钮不会触发blur动作,这使得用户体验非常不好。

判断在安卓手机的情况下做如下处理:

const originalHeight = document.documentElement.clientHeight || document.body.clientHeight;
window.onresize = function() {
    var resizeHeight = document.documentElement.clientHeight || document.body.clientHeight;
    if (resizeHeight - 0 >= originalHeight - 0) {
        document.activeElement.blur();
    }
};

注:安卓手机不能使用focusout来监听软键盘收起,只能监听onresize事件。

3. 使用rem适配

设计团队的设计稿是基于iPhone6s做的,也就是长宽比为375:667。他们希望在其他设备上等比缩放。

所以我们使用了rem的方式,并且没有使用媒体查询在不同的宽度桑设置不同的font-size。而是使用了现有的轮子

    ;
    (function (designWidth, maxWidth) {
      var doc = document,
        win = window,
        docEl = doc.documentElement,
        remStyle = document.createElement("style"),
        tid;

      function refreshRem() {
        var width = docEl.getBoundingClientRect().width;
        maxWidth = maxWidth || 540;
        width > maxWidth && (width = maxWidth);
        var rem = width * 16 / designWidth;
        remStyle.innerHTML = 'html{font-size:' + rem + 'px;}';
      }

      if (docEl.firstElementChild) {
        docEl.firstElementChild.appendChild(remStyle);
      } else {
        var wrap = doc.createElement("div");
        wrap.appendChild(remStyle);
        doc.write(wrap.innerHTML);
        wrap = null;
      }
      //要等 wiewport 设置好后才能执行 refreshRem,不然 refreshRem 会执行2次;
      refreshRem();

      win.addEventListener("resize", function () {
        clearTimeout(tid); //防止执行两次
        tid = setTimeout(refreshRem, 300);
      }, false);

      win.addEventListener("pageshow", function (e) {
        if (e.persisted) { // 浏览器后退的时候重新计算
          clearTimeout(tid);
          tid = setTimeout(refreshRem, 300);
        }
      }, false);

      if (doc.readyState === "complete") {
        doc.body.style.fontSize = "16px";
      } else {
        doc.addEventListener("DOMContentLoaded", function (e) {
          doc.body.style.fontSize = "16px";
        }, false);
      }
    })(375, 750);

使用js动态计算,经测试这种方案效果最佳。

4. 滑动穿透问题

在移动端,弹出层的滑动会使得弹出层下端的页面跟着滚动,这给使用者造成了很不好的效果。 在社区针对这个问题有个很成熟的解决方案:

body-scroll-lock

使用方式也很简单:

const bodyScrollLock = require('body-scroll-lock');
const disableBodyScroll = bodyScrollLock.disableBodyScroll;
const enableBodyScroll = bodyScrollLock.enableBodyScroll;

const targetElement = document.querySelector("#弹出层元素");
if(条件) disableBodyScroll(targetElement);
else enableBodyScroll(targetElement);

H5开发中最蛋疼的应该就是兼容性问题,这个过程很考验开发者的经验和耐心。

以上有什么不对的地方或更好的解决方案,欢迎大家留言交流。😄