前言
关于Vue适配移动端目前有几种方案:rem、vh/vw等等,各有优缺吧,根据自己项目的特点我选用的是postcss,它可以自动将px转换成rem,所以是rem方案的一种。
下面来看看如何使用它。
postcss
首先安装postcss-pxtorem
pnpm install --save postcss-pxtorem@5.1.1
然后在package.json中添加:
{
"name": "xxxxx",
"version": "1.0.0",
...
"postcss": {
"plugins": {
"postcss-pxtorem": {
"rootValue": 43.75,
"propList": [
"*"
]
}
}
},
...
}
这里的rootValue就是我们假设的1rem的大小,这样postcss就会根据rootValue自动将css中设置的px值转成rem值:rem = px / rootValue
但是实际展示的时候,会将rem转换成像素大小,这时候是根据项目中默认字体来计算的,比如在index.html中设置的默认字体大小是43.75
<!DOCTYPE html>
<html lang="zh-cmn-Hans" style="font-size: 43.75px;">
...
这样实际上展示的时候会1rem转为43.75px。
所以经过postcss转换后的 最终大小 = 原大小 / rootValue * rootfontSize
所以如果rootValue和rootfontSize设置一致,展示的就是原尺寸,如果rootValue大于rootfontSize,尺寸就会缩小。
这样我们设置好rootValue后,可以通过改变rootfontSize就可以动态改变展示尺寸,比如我们可以根据窗口的宽度来动态改变rootfontSize,比如在App.vue中:
onMounted(() => {
resizeFontSize();
window.addEventListener("resize", resizeFontSize, false);
});
const resizeFontSize = () => {
const windowWidth = document.documentElement.clientWidth || document.body.clientWidth;
const htmlDom = document.getElementsByTagName("html")[0];
htmlDom.style.fontSize = `${windowWidth / 30}px`;
};
这样当窗口缩小的是,所有的尺寸都会跟着缩小,达到适配的效果。
或者可以根据屏幕密度来设置rootfontSize,比如:
onMounted(() => {
resizeFontSize();
});
const resizeFontSize = () => {
const baseFontSize = 43.75;
const htmlDom = document.getElementsByTagName("html")[0];
const retio = isMobile() ? window.devicePixelRatio : 1;
htmlDom.style.fontSize = `${baseFontSize / retio}px`;
};
这里只在移动端根据屏幕密度切换,在pc端保持原尺寸不变。
或者在移动端根据屏幕宽度适配,在pc端保持不变,如下:
onMounted(() => {
resizeFontSize();
});
const resizeFontSize = () => {
const baseFontSize = 43.75;
const htmlDom = document.getElementsByTagName("html")[0];
const retio = isMobile() ? getMobileRetio() : 1;
htmlDom.style.fontSize = `${baseFontSize / retio}px`;
};
const getMobileRetio = () => {
const windowWidth =
document.documentElement.clientWidth || document.body.clientWidth;
const windowHeight =
document.documentElement.clientHeight || document.body.clientHeight;
const width = Math.max(windowWidth, windowHeight);
if (width > 1440) {
return 1;
}
return 1440 / width;
};
这里我们限制了一个大小,如果超过这个就不需要继续放大,而是通过空间调整达到适配,这样防止字体显得更大。而且我们在移动端是横屏观看的,所以这里通过对比width和height来得到宽度。
总之大家根据自己的实际情况来制定适配策略。
style
注意postcss-pxtorem只会替换css即class中的px,对于style中的px则不会处理,所以在html中通过style来设置默认字体<html lang="zh-cmn-Hans" style="font-size: 43.75px;">
,这样就不会被postcss-pxtorem影响。所以这时候的项目中的style就尽量不要设置尺寸,如果需要设置则需要直接使用rem。
flexible
上面使用postcss-pxtorem后,如果不动态改变rootfontSize其实对适配并没有太多帮助,因为大小屏幕上尺寸一致,这样大屏幕上显示的内容更多。上面我们自己实现了修改rootfontSize,还可以使用amfe-flexible。
amfe-flexible使用起来非常简单,首先安装:
pnpm install amfe-flexible --save
然后在main.js中import即可:
import { createApp } from "vue";
...
import "amfe-flexible";
createApp(App).use(store).use(router).mount("#app");
运行就会发现在不同端上展现的内容是一样的,在大屏幕上字体等更大了。
通过开发者工具看可以看到amfe-flexible实际上就是改变了rootfontSize,将rootfontSize设置为宽度的十分之一,在它的源码中可以看到:
// set 1rem = viewWidth / 10
function setRemUnit () {
var rem = docEl.clientWidth / 10
docEl.style.fontSize = rem + 'px'
}
setRemUnit()
// reset rem unit on page resize
window.addEventListener('resize', setRemUnit)
window.addEventListener('pageshow', function (e) {
if (e.persisted) {
setRemUnit()
}
})
所以跟我们上面做的方式是一样的,但是用起来更方便一些。