H5常见问题及解决方案手册,【一篇文章搞懂】

我们在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)恢复成原来的视口

iPhone X系列安全区域适配问题


表现

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

产生原因

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

解决方案

设置安全区域,填充危险区域,危险区域不做操作和内容展示。

危险区域指头部不规则区域,底部横条区域,左右触发区域。

具体操作为:viewport-fit meta 标签设置为 cover,获取所有区域填充。判断设备是否属于 iPhone X,给头部底部增加适配层

viewport-fit 有 3 个值分别为:

  • auto:此值不影响初始布局视图端口,并且整个web页面都是可查看的。
  • contain:视图端口按比例缩放,以适合显示内嵌的最大矩形。
  • cover:视图端口被缩放以填充设备显示。强烈建议使用 safe area inset 变量,以确保重要内容不会出现在显示之外。
设置 viewport-fit 为 cover
增加适配层

使用 safe area inset 变量

/* 适配 iPhone X 顶部填充*/

@supports (top: env(safe-area-inset-top)){

body,

.header{

padding-top: constant(safe-area-inset-top, 40px);

padding-top: env(safe-area-inset-top, 40px);

padding-top: var(safe-area-inset-top, 40px);

}

}

/* 判断iPhoneX 将 footer 的 padding-bottom 填充到最底部 */

@supports (bottom: env(safe-area-inset-bottom)){

body,

.footer{

padding-bottom: constant(safe-area-inset-bottom, 20px);

padding-bottom: env(safe-area-inset-bottom, 20px);

padding-top: var(safe-area-inset-bottom, 20px);

}

}

safe-area-inset-topsafe-area-inset-rightsafe-area-inset-bottomsafe-area-inset-left safe-area-inset-*由四个定义了视口边缘内矩形的 toprightbottom 和 left 的环境变量组成,这样可以安全地放入内容,而不会有被非矩形的显示切断的风险。对于矩形视口,例如普通的笔记本电脑显示器,其值等于零。对于非矩形显示器(如圆形表盘,iPhoneX 屏幕),在用户代理设置的四个值形成的矩形内,所有内容均可见。

其中 env() 用法为 env( <custom-ident> , <declaration-value>? ),第一个参数为自定义的区域,第二个为备用值。

其中 var() 用法为 var( <custom-property-name> , <declaration-value>? ),作用是在 env() 不生效的情况下,给出一个备用值。

constant() 被 css 2017-2018 年为草稿阶段,是否已被标准化未知。而其他iOS 浏览器版本中是否有此函数未知,作为兼容处理而添加进去。

详情请查看文章末尾的参考资料。

兼容性

页面生成为图片和二维码问题


表现

在工作中有需要将页面生成图片或者二维码的需求。可能我们第一想到的,交给后端来生成更简单。但是这样我们需要把页面代码全部传给后端,网络性能消耗太大。

解决方案

生成二维码

使用 QRCode 生成二维码

import QRCode from ‘qrcode’;

// 使用 async 生成图片

const options = {};

const url = window.location.href;

async url => {

try {

console.log(await QRCode.toDataURL(url, options))

} catch (err) {

console.error(err);

}

}

将 await QRCode.toDataURL(url, options) 赋值给 图片 url 即可

生成图片

主要是使用 htmlToCanvas 生成 canvas 画布

import html2canvas from ‘html2canvas’;

html2canvas(document.body).then(function(canvas) {

document.body.appendChild(canvas);

});

但是不单单在此处就完了,由于是 canvas 的原因。移动端生成出来的图片比较模糊。

我们使用一个新的 canvas 方法多倍生成,放入一倍容器里面,达到更加清晰的效果,通过超链接下载图片 下载文件简单实现,更完整的实现方式之后更新

const scaleSize = 2;

const newCanvas = document.createElement(“canvas”);

const target = document.querySelector(‘div’);

const width = parseInt(window.getComputedStyle(target).width);

const height = parseInt(window.getComputedStyle(target).height);

newCanvas.width = width * scaleSize;

newCanvas.height = widthh * scaleSize;

newCanvas.style.width = width + “px”;

newCanvas.style.height =width + “px”;

const context = newCanvas.getContext(“2d”);

context.scale(scaleSize, scaleSize);

html2canvas(document.querySelector(‘.demo’), { canvas: newCanvas }).then(function(canvas) {

// 简单的通过超链接设置下载功能

document.querySelector(“.btn”).setAttribute(‘href’, canvas.toDataURL());

}

根据需要设置 scaleSize 大小

微信公众号分享问题


表现

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

解决方案

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

因为页面内部点击分享按钮无法直接调用,而分享功能需要点击右上角更多来操作。

然后用户可能不知道通过右上角小标里面的功能分享。又想引导用户分享,这时应该怎么做呢?

技术无法实现的,从产品出发。

如果技术上实现复杂,或者直接不能实现。不要强行钻牛角尖哦,学会怼产品,也是程序员必备的能力之一。

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’)

})

  1. 回调方法 bridge.call

export const getSDKVersion = () => bridge.call(‘BLT.getSDKVersion’)

事件监听与触发法

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’)

}

}

同一功能需要iOS,Android方法名相同,这样更好处理哦

H5 调试相关方案策略


表现

调试代码一般就是为了查看数据定位 bug。分为两种场景,一种是开发和测试时调试,一种是生产环境上调试。

为什么有生产环境上调试呢?有些时候测试环境上没法复现这个 bug,测试环境和生产环境不一致,此时就需要紧急生产调试。

在 PC 端开发时,我们可以直接掉出控制台,使用浏览器提供的工具操作devtools或者查看日志。但是在 App 内部我们怎么做呢?

原理与解决方案

1. vconsole 控制台插件

使用方法也很简单

import Vconsole from ‘vconsole’

new Vconsole()

有兴趣看看它实现的基本原理,我们关注的点应该在 vsconsole 如何打印出我们所有 log 的 腾讯开源vconsole

上述方法仅用于开发和测试。生产环境中不允许出现,所以,使用时需要对环境进行判断。

import Vconsole from ‘vconsole’

if (process.env.NODE_ENV !== ‘production’) {

new Vconsole()

}

2. 代理 + spy-debugger

操作稍微有点麻烦,不过我会详细写出,大致分为 4 个步骤

  1. 安装插件(全局安装)

sudo npm install spy-debugger -g

  1. 手机与电脑置于同一 wifi 下,手机设置代理

小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Web前端开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img
img
img
img

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频

如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注:前端)
img

最后

面试题千万不要死记,一定要自己理解,用自己的方式表达出来,在这里预祝各位成功拿下自己心仪的offer。
开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

大厂面试题

面试题目录

因此收集整理了一份《2024年Web前端开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。**

[外链图片转存中…(img-kwWziKsn-1710963554056)]
[外链图片转存中…(img-eKgG5aso-1710963554056)]
[外链图片转存中…(img-JWqCpe8x-1710963554057)]
[外链图片转存中…(img-3Buxuz5q-1710963554057)]

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频

如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注:前端)
[外链图片转存中…(img-gQNGmFdI-1710963554058)]

最后

面试题千万不要死记,一定要自己理解,用自己的方式表达出来,在这里预祝各位成功拿下自己心仪的offer。
开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

[外链图片转存中…(img-2At1oCSK-1710963554058)]

[外链图片转存中…(img-FliCHuFd-1710963554059)]

[外链图片转存中…(img-XhS3MPEH-1710963554059)]

[外链图片转存中…(img-ILBNagXQ-1710963554059)]

  • 25
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值