h5项目问题总结
# h5 项目问题总结
记录写 h5 页面遇到的一些问题以及解决方法
# ios 和 android 键盘弹起的区别
# 区别
- ios 键盘弹起会造成页面向上滚动(整个 html 页面移动),android 键盘弹起是键盘覆盖在视口上(html 页面不会移动,视口区域变化所以会触发 resize 事件)
- android 键盘弹起会触发页面的 resize 事件(ios 不会),ios 在键盘收起的时候 input 会失去焦点(安卓不会,使用原生 input 框的情况)
- ios 在键盘弹起时页面滚动,收起时可能回不到原来的位置(android 不会)
# 问题
# android 键盘弹起时 input 框不遮挡
描述:
ios 中 focus 触发时,页面会向上滚动,input 出现在视口位置,不存在遮挡问题
android 中 focus 触发时,整个视口高度变宽,input 有可能会被遮挡
解决:
- ios 中几乎不用做处理
- android 中通过监听 focus 事件,将 输入框滚动到视口位置(或者将元素定位到键盘上方)
// TODO: 待完善
1
# 监听键盘的收起状态
描述:
ios 触发软键盘上的“收起”按钮键盘或者输入框以外的页面区域时,输入框失去焦点,软键盘收起。
android 触发软键盘上的“收起”按钮键盘或者输入框以外的页面区域时,软键盘收起,但输入框没有失去焦点。
解决:
- ios 上通过监听 focus、blur 事件来获取键盘的状态
- android 上键盘弹起和收起状态时,会触发页面的 resize 事件,所以通过监听 resize 事件可以知道键盘收起(focus 触发的前提)
// 监听输入框的软键盘弹起和收起事件
function listenKeybordStatus($input) {
const _input = document.getElementById("input");
if ("ios") {
// 自行判断
// IOS 键盘弹起:IOS 和 Android 输入框获取焦点键盘弹起
_input.addEventListener(
"focus",
function() {
console.log("ios 键盘弹起啦!");
// TODO
},
false
);
// IOS 键盘收起:IOS 点击输入框以外区域或点击收起按钮,输入框都会失去焦点,键盘会收起
_input.addEventListener("blur", () => {
console.log("ios 键盘收起啦!");
// TODO
});
}
// android 键盘收起:android 键盘弹起或收起页面高度会发生变化
if ("android") {
// 自行判断
let originHeight =
document.documentElement.clientHeight || document.body.clientHeight;
window.addEventListener(
"resize",
function() {
const resizeHeight =
document.documentElement.clientHeight || document.body.clientHeight;
if (originHeight < resizeHeight) {
console.log("android 键盘收起啦!");
// TODO
} else {
console.log("android 键盘弹起啦!");
// TODO
}
originHeight = resizeHeight;
},
false
);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# ios 键盘弹起页面可滚动
描述:
在 ios 中,键盘弹起状态,页面还可以滚动
android 中没有这个情况
解决:
- ios 中在键盘弹起时,给页面添加 touchmove 事件触发后收起键盘(引出的问题:键盘弹起时页面的 长按时间也会触发 touchmove)
- ios 中用户滚动页面的时候,手动触发 blur
- 暂时未能做到 ios 在键盘弹起的时候,禁用页面滚动,只能通过这种方式来换个思路解决问题
document.body.addEventListener("touchmove", onTouchMove.bind(this));
// 手动失焦
function onTouchMove() {
document.getElementById("input").blur();
}
1
2
3
4
5
2
3
4
5
# android 中定位在页面右下角的元素在键盘弹起时未消失
描述:
需求中需要在页面右下角定位入口元素的情况
此时键盘弹起时,在 ios 中定位元素会消失,在 android 中 定位元素不消失,且会跟着键盘弹起而向上移动
效果
解决:
- android 中键盘弹起会触发 resize 事件,判断触发前后视口的高度
// 适配安卓键盘弹出定位问题
const initInnerHeight = window.innerHeight;
window.addEventListener("resize", () => {
const showContact = window.innerHeight >= initInnerHeight; // 隐藏定位元素
document.getElementById("contact").style.display = showContact ? "" : "none";
});
1
2
3
4
5
6
2
3
4
5
6
# ios 底部 safe area 问题
描述:
部分 ios 机型 存在 safe area
主要表现在底部会有一个居中的黑条,效果如下
页面内容布局不想被 黑条 遮挡,就可以使用 ios 提供的 api 来改变页面布局
效果
解决:
- 使用到的属性
- safe-area-inset-left:安全区域距离左边边界的距离
- safe-area-inset-right:安全区域距离右边边界的距离
- safe-area-inset-top:安全区域距离顶部边界的距离
- safe-area-inset-bottom :安全距离底部边界的距离
/* 设置 padding-bottom 的像素,使元素内容不会出现在 小黑条 区域 */
padding-bottom: constant(safe-area-inset-bottom); /* 兼容 iOS < 11.2 */
padding-bottom: env(safe-area-inset-bottom); /* 兼容 iOS >= 11.2 */
1
2
3
2
3
# 计算页面滚动距离
描述:
h5 中未设置 overflow: auto,属性,但页面滚动了
解决:
const len = window.pageYOffset || document.documentElement.scrollTop || 0;
1
# 附件下载
流文件下载
请求头需要添加 responseType: 'blob'
描述:
响应头中带有 Content-Type: application/octet-stream(有 stream 等明显标记的)
附件下载分为 get 和 post 下载
get 下载:
- 触发浏览器对无法解析的文件会进行下载
window.open(downloadUrl); // 方式一
1
<a href="downloadUrl">点击下载</a>
1
post 下载:
- 通过
URL.createObjectURL
创建 一个指向源 Object 的 URL 对象 - 将该 URL 对象 赋值给 a 标签,再触发 下载
axios({
url: "downloadUrl",
method: "POST",
data: {
analysisId: "analysisId",
},
responseType: "blob",
})
.then((res) => {
const blob = new Blob([res], {
type: "text/csv",
});
const URL = window.URL || window.webkitURL || window.moxURL; // 兼容
// 创建下载链接,会将文件存在内存中
const blobUrl = URL.createObjectURL(blob);
// 构建 a 标签
const a = document.createElement("a");
a.download = "分析数据.xlsx";
a.href = blobUrl;
document.body.appendChild(a);
// 触发 a 标签的点击,自动下载
a.click();
// 释放下载链接,删除内存中的文件
URL.revokeObjectURL(a.href);
document.body.removeChild(a);
})
.catch((err) => {
console.log("下载失败:", err);
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
上次更新: 2021/12/10, 14:32:24