# 获取 dom 元素信息
这个方法在 PC 端和移动端都能支持。
export const getDomInfo = (classname: string) => {
return (
document.getElementsByClassName(classname)[0]?.getBoundingClientRect() || {}
);
};
2
3
4
5
# scrollTop 兼容性
- 以下获取 scrollTop 的方法在 PC 端和苹果手机上能生效,但是安卓手机上不生效:
const handleScroll = (e) => {
const scrollTop = e.srcElement.documentElement.scrollTop;
};
const scrollTop = document.documentElement.scrollTop;
2
3
4
5
- 以下获取 scrollTop 的方法在 PC 端和苹果手机上不生效,只在安卓手机上生效:
const scrollTop = document.body.scrollTop;
- 以下获取 scrollTop 的方法在 PC 端和移动端都生效:
// window.pageYOffset 是一个只读属性
const scrollY = window.pageYOffset;
// 在 PC 端 document.scrollingElement 就是 document.documentElement
// 在移动端 document.scrollingElement 就是 document.body
const scrollTop = document.scrollingElement.scrollTop;
2
3
4
5
6
window.pageYOffset 对 IE 和移动端的支持都不错,能支持到 IE9+ 和 Android 4+。
document.scrollingElement 对 IE 的兼容性不好,移动端就还不错,能支持到 Android 5+。可以使用 document.scrollingElement 的 Polyfill (opens new window) 兼容一些老旧设备。
- 之前 scrollTop 常见的兼容性写法如下:
const scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
不过现在可以不用这么写了,如果只是想要获取窗体的滚动高度,直接使用 window.pageYOffset;如果需要设置窗体的滚动高度,直接使用 document.scrollingElement 就可以了。
# getBoundingClientRect().top 判断在真机上会一直闪
移动端常见的一些吸顶效果是需要通过 scrollTop 或者 getBoundingClientRect().top 来判断的,只有当滚动到一定位置时才展示吸顶效果(通过添加类名或者控制显示隐藏)。
下面这两种方法,前者在真机上是正常的吸顶效果,但是后者在真机上看到的效果是会一直闪,很不好,不知道啥原因。
const handleScroll = () => {
const scrollY = window.pageYOffset;
if (scrollY > 127) {
setFixed(true);
} else {
setFixed(false);
}
};
2
3
4
5
6
7
8
const handleScroll = () => {
const top = document
.getElementsByClassName(classname)[0]
?.getBoundingClientRect().top;
if (top <= 0) {
setFixed(true);
} else {
setFixed(false);
}
};
2
3
4
5
6
7
8
9
10
# 安卓手机企微环境 wx.miniProgram 为 undefined
如标题所示,在苹果手机上的企微里是正常的,但是在安卓手机上的企微里就报错了,开发时注意做好容错处理。
企业微信-微信小程序 API 支持情况 (opens new window)
# 移动端 1px 问题及解决方案
1px 问题指的是在一些 Retina 屏幕 的机型上,移动端页面的 1px 会变得很粗,呈现出不止 1px 的效果。
产生这个问题的原因很简单,CSS 中的 1px 并不能和移动设备上的 1px 划等号。它们之间的比例关系有一个专门的属性来描述:
// 设备像素比
window.devicePixelRatio = 设备的物理像素 / CSS 像素
2
一个物理像素等于多少个设备像素取决于移动设备的屏幕特性(是否是 Retina)和用户缩放比例。
比如如果设备像素比为 2,那么就意味着 1px 的 CSS 像素,在移动端上会用 2 个物理像素来进行渲染,所以实际看到的一定会比 1px 粗一些。
目前针对 1px 问题推荐的解决方法是伪元素先放大后缩小或者设置 viewport 来解决问题。
# 伪元素先放大后缩小
在目标元素的后面追加一个 ::after 伪元素,让这个元素布局为 absolute 之后,整个伸展开铺在目标元素上,然后把它的宽和高都设置为目标元素的两倍,border 值设为 1px。接着借助 CSS 动画特效中的放缩能力,把整个伪元素缩小为原来的 50%。此时,伪元素的宽高刚好可以和原有的目标元素对齐,而 border 也缩小为了 1px 的二分之一,间接地实现了 0.5px 的效果。
目前大部分移动端 UI 采用该方案,全机型兼容。
.border_base(@scalew: 1, @scaleh: 1, @radius: 0) {
position: relative;
&::after {
position: absolute;
content: '';
left: 0;
top: 0;
width: 100% * @scalew;
height: 100% * @scaleh;
// @TODO transform-origin: 5% 在 ios 与安卓下的表现不一致,所以暂时不用这种方式
transform-origin: ((1 - @scalew)/2 * 100%) ((1 - @scaleh)/2 * 100%);
pointer-events: none; /* 防止点击触发 */
border-radius: @radius;
}
@media only screen and (-webkit-min-device-pixel-ratio: 2) {
&::after {
width: 200% * @scalew;
height: 200% * @scaleh;
transform: scale(0.5);
border-radius: @radius*2;
}
}
@media only screen and (-webkit-min-device-pixel-ratio: 3) {
&::after {
width: 300% * @scalew;
height: 300% * @scaleh;
transform: scale(0.333);
border-radius: @radius*3;
}
}
}
.border_1px(@color: #ccc, @radius: 0) {
.border_base(1, 1, @radius);
&::after {
border: 1px solid @color;
}
}
.border_1px_top(@color: #ccc, @scalew: 1) {
.border_base(@scalew, 1);
&::after {
border-top: 1px solid @color;
}
}
.border_1px_bottom(@color: #ccc, @scalew: 1) {
.border_base(@scalew, 1);
&::after {
border-bottom: 1px solid @color;
}
}
.border_1px_left(@color: #ccc, @scaleh: 1) {
.border_base(1, @scaleh);
&::after {
border-left: 1px solid @color;
}
}
.border_1px_right(@color: #ccc, @scaleh: 1) {
.border_base(1, @scaleh);
&::after {
border-right: 1px solid @color;
}
}
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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# 设置 viewport 来解决问题
利用 viewport + rem + js 来实现,边框直接写上 1px 会自动转换。
这种方式也是全机型兼容,代码里可以直接写 1px 简单方便!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta
name="viewport"
id="WebViewport"
content="initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no"
/>
<title>Document</title>
<style type="text/css"></style>
</head>
<body>
<script type="text/javascript">
let viewport = document.querySelector("meta[name=viewport]");
// 根据设备像素设置 viewport
if (window.devicePixelRatio == 1) {
viewport.setAttribute(
"content",
"width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no"
);
}
if (window.devicePixelRatio == 2) {
viewport.setAttribute(
"content",
"width=device-width, initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5, user-scalable=no"
);
}
if (window.devicePixelRatio == 3) {
viewport.setAttribute(
"content",
"width=device-width, initial-scale=0.3333333333333333, maximum-scale=0.3333333333333333, minimum-scale=0.3333333333333333, user-scalable=no"
);
}
function resize() {
const width = screen.width > 750 ? "75px" : screen.width / 10 + "px";
document.getElementsByTagName("html")[0].style.fontSize = width;
}
window.onresize = resize;
</script>
</body>
</html>
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