移动端H5常见问题汇总

移动端H5相关问题汇总

  • 自适应问题
  • iOS 滑动不流畅
  • iOS 上拉边界下拉出现白色空白
  • 页面件放大或缩小不确定性行为
  • click 点击穿透与延迟
  • 软键盘弹出将页面顶起来、收起未回落问题
  • iPhone X 底部栏适配问题
  • H5 调试相关方案与策略
  • H5 调用 SDK 相关问题及解决方案

移动端 H5 相关基础技术概览

在这里插入图片描述

1、自适应问题

对于开发h5来说肯定要考虑到自适应问题,目前来说大多数的解决方法都是将px转化为rem,当然也可以使用vh,vw单位,但是个人觉得使用rem是最好的解决方案。

  1. 使用postcss-pxtorem
    postcss-pxtorem是PostCSS的插件,用于将像素单元生成rem单位。

1.安装依赖

npm install postcss-pxtorem -D

2.设置规则(更改postcss.config.js,该文件为使用vue-cli3自动创建的文件)

module.exports = {
  plugins: {
    'autoprefixer': {
      browsers: ['Android >= 4.0', 'iOS >= 7']
    },
    'postcss-pxtorem': {
      rootValue: 16,//结果为:设计稿元素尺寸/16,比如元素宽320px,最终页面会换算成 20rem
      propList: ['*']
    }
  }
}
  1. 设置最顶层父级font-size,所有单位使用rem
 * 基于iphone375宽度的基准做制作,把body的font-size按比例设置成约等于10px
 * 设置字体大小用单位em  1em=10px,1.4em=14px....以此类推
 * @type {string}
 */
// document.getElementsByTagName("body")[0].style.fontSize = document.body.clientWidth / 37.5 + 'px';

if (document.documentElement.clientWidth > 640) {
    document.documentElement.style.fontSize =
        640 / 3.75 / 2 + 'px'
} else {
    document.documentElement.style.fontSize =
        document.documentElement.clientWidth / 3.75 / 2 + 'px'
}
2、iOS 滑动不流畅

问题描述:上下滑动页面会产生卡顿,手指离开页面,页面立即停止运动。整体表现就是滑动不流畅,没有滑动惯性。
原因:原来在 iOS 5.0 以及之后的版本,滑动有定义有两个值 auto 和 touch,默认值为 auto。

-webkit-overflow-scrolling: touch; /* 当手指从触摸屏上移开,会保持一段时间的滚动 */

-webkit-overflow-scrolling: auto; /* 当手指从触摸屏上移开,滚动会立即停止 */

解决方法:

.wrapper {
    -webkit-overflow-scrolling: touch;
}
body {
    overflow-y: hidden;
}
.wrapper {
    overflow-y: auto;
}
// 设置滚动条隐藏: .container ::-webkit-scrollbar {display: none;}
3、iOS 上拉边界下拉出现白色空白

问题描述: 手指按住屏幕下拉,屏幕顶部会多出一块白色区域。手指按住屏幕上拉,底部多出一块白色区域。

原因: 在 iOS 中,手指按住屏幕上下拖动,会触发 touchmove 事件。这个事件触发的对象是整个 webview 容器,容器自然会被拖动,剩下的部分会成空白。
解决方案: 监听事件禁止滑动

1. touchstart :手指放在一个DOM元素上。
2. touchmove :手指拖曳一个DOM元素。
3. touchend :手指从一个DOM元素上移开。

document.body.addEventListener('touchmove', function(e) {
    if(e._isScroller) return;
    // 阻止默认事件
    e.preventDefault();
}, {
    passive: false
});
4、click 点击事件延时与穿透

问题描述: 监听元素 click 事件,点击元素触发时间延迟约 300ms。
点击蒙层,蒙层消失后,下层元素点击触发。

产生原因: iOS 中的 safari,为了实现双击缩放操作,在单击 300ms 之后,如果未进行第二次点击,则执行 click 单击操作。也就是说来判断用户行为是否为双击产生的。但是,在 App 中,无论是否需要双击缩放这种行为,click 单击都会产生 300ms 延迟。

解决方案:
1、使用 touchstart 替换 click

移动设备不仅支持点击,还支持几个触摸事件。那么我们现在基本思路就是用 touch 事件代替click 事件。
将 click 替换成 touchstart 不仅解决了 click 事件都延时问题,还解决了穿透问题。因为穿透问题是在 touch 和 click 混用时产生。

// 原生方法
el.addEventListener("touchstart", () => { console.log("ok"); }, false);

// vue方法
<button @touchstart="handleTouchstart()">点击</button>

2、使用 fastclick 库

// fastclick 库可以使click 延时和穿透问题都没了,但是需要安装依赖
// fastclick源码 核心代码不长, 1000 行不到。有兴趣可以了解一下!

import FastClick from 'fastclick';

FastClick.attach(document.body, options);

5、软键盘将页面顶起来、收起未回落问题

问题描述: Android 手机中,点击 input 框时,键盘弹出,将页面顶起来,导致页面样式错乱。
移开焦点时,键盘收起,键盘区域空白,未回落。

产生原因: 我们在app 布局中会有个固定的底部。安卓一些版本中,输入弹窗出来,会将解压 absolute 和 fixed 定位的元素。导致可视区域变小,布局错乱。

解决方法: 其实就是通过监听页面高度变化,强制恢复成弹出前的高度。

// 记录原有的视口高度
const originalHeight = document.body.clientHeight || document.documentElement.clientHeight;

window.onresize = function(){
  var resizeHeight = document.documentElement.clientHeight || document.body.clientHeight;
  if(resizeHeight < originalHeight ){
    // 恢复内容区域高度
    // const container = document.getElementById("container")
    // 例如 container.style.height = originalHeight;
  }
}

键盘不能回落问题出现在 iOS 12+ 和 wechat 6.7.4+ 中,而在微信 H5 开发中是比较常见的 Bug。
兼容原理,1.判断版本类型 2.更改滚动的可视区域

const isWechat = window.navigator.userAgent.match(/MicroMessenger\/([\d\.]+)/i);
if (!isWechat) return;
const wechatVersion = wechatInfo[1];
const version = (navigator.appVersion).match(/OS (\d+)_(\d+)_?(\d+)?/);
 
 // 如果设备类型为iOS 12+ 和wechat 6.7.4+,恢复成原来的视口
if (+wechatVersion.replace(/\./g, '') >= 674 && +version[1] >= 12) {
  window.scrollTo(0, Math.max(document.body.clientHeight, document.documentElement.clientHeight));
}

// window.scrollTo(x-coord, y-coord),其中window.scrollTo(0, clientHeight)恢复成原来的视口
6、iPhone X系列安全区域适配问题

问题描述: 头部刘海两侧区域或者底部区域,出现刘海遮挡文字,或者呈现黑底或白底空白区域。

产生原因: iPhone X 以及它以上的系列,都采用刘海屏设计和全面屏手势。头部、底部、侧边都需要做特殊处理。才能适配 iPhone X 的特殊情况。

解决方法:
1、设置安全区域,填充危险区域,危险区域不做操作和内容展示。
设置 viewport-fit 为 cover

<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes, viewport-fit=cover">
7、页面生成为图片和二维码问题

生成二维码
使用 QRCode 生成二维码

// 在vue中实现
<template>
<div id="qrcode"
     ref="qrcode"
     class="scan">
</div>
</template>

import QRCode from 'qrcodejs2';

mounted () {
    // setTimeout(() => {
    //   this.toImage()
    // }, 3000);
    this.$nextTick(() => {
      this.qrcode();
    });
  },
// 生成二维码
    qrcode () {
      let qrcode = new QRCode('qrcode', {
        width: 188, // 二维码宽度,单位像素
        height: 192, // 二维码高度,单位像素
        text: this.resp.url // 生成二维码的链接
      });
    },

生成图片
生成图片的在之前的博客上有,大家可以翻一翻

8、微信公众号分享问题

问题描述: 在微信公众号 H5 开发中,页面内部点击分享按钮调用 SDK,方法不生效。

解决方法: 添加一层蒙层,做分享引导。

9、H5 调用 SDK 相关解决方案

产生原因: 在 Hybrid App 中使用 H5 是最常见的不过了,刚接触的,肯定会很生疏模糊。不知道 H5 和 Hybrid 是怎么交互的。怎样同时支持 iOS 和 Android 呢?现在来谈谈 Hybrid 技术要点,原生与 H5 的通信。

解决方案: 使用 DSBridge 同时支持 iOS 与 Android

SDK小组 提供方法:
1、注册方法 bridge.register

bridge.register('enterApp', function() {
  broadcast.emit('ENTER_APP')
})

2、回调方法 bridge.call

export const getSDKVersion = () => bridge.call('BLT.getSDKVersion')

3、事件监听与触发法

const broadcast = {
  on: function(name, fn, pluralable) {
    this._on(name, fn, pluralable, false)
  },
  once: function(name, fn, pluralable) {
    this._on(name, fn, pluralable, true)
  },
  _on: function(name, fn, pluralable, once) {
    let eventData = broadcast.data
    let fnObj = { fn: fn, once: once }
    if (pluralable && Object.prototype.hasOwnProperty.call(eventData, 'name')) {
      eventData[name].push(fnObj)
    } else {
      eventData[name] = [fnObj]
    }
    return this
  },
  emit: function(name, data, thisArg) {
    let fn, fnList, i, len
    thisArg = thisArg || null
    fnList = broadcast.data[name] || []
    for (i = 0, len = fnList.length; i < len; i++) {
      fn = fnList[i].fn
      fn.apply(thisArg, [data, name])
      if (fnList[i].once) {
        fnList.splice(i, 1)
        i--
        len--
      }
    }
    return this
  },
  data: {}
}
export default broadcast

踩坑注意
方法调用前,一定要判断 SDK 是否提供该方法 如果 Android 提供该方法,iOS 上调用就会出现一个方法调用失败等弹窗。怎么解决呢?

提供一个判断是否 Android、iOS。根据设备进行判断

export const hasNativeMethod = (name) =>
  return bridge.hasNativeMethod('BYJ.' + name)
}

export const getSDKVersion = function() {
  if (hasNativeMethod('getSDKVersion')) {
    bridge.call('BYJ.getSDKVersion')
  }
}
  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值