Vue中pc端与移动端适配解决方案
0. 前言
目前常见屏幕适配方案很多,眼花缭乱,比如:postcss-pxtorem、postcss-px2rem、px2rem-loader、postcss-plugin-px2rem,由于时间经历有限,没有依次了解测试,本着解决问题的考虑,优先采用效果可以实现的方式。 移动端,pc端适配方案建议如下: 建议将移动端和pc端进行拆分,工程化配置,导致项目整体框架发生更改,部分页面更改后发生笔记本电脑,显示比例缩放后轻微不协调,可以看下面图片。可以通过插入【整体缩放自适应解决方案(阿里团队高清方案)JS代码解决】。
1.移动端适配方案
1.1 基础概念
viewport即视窗、视口,用于显示网页部分的区域,在PC端视口即是浏览器窗口区域,在移动端,为了让页面展示更多的内容,视窗的宽度默认不为设备的宽度,在移动端视窗有三个概念:布局视窗、视觉视窗、理想视窗。
- 布局视窗:在浏览器窗口css的布局区域,布局视口的宽度限制css布局的宽。为了能在移动设备上正常显示那些为pc端浏览器设计的网站,移动设备上的浏览器都会把自己默认的viewport设为980px或其他值,一般都比移动端浏览器可视区域大很多,所以就有横向滚动条。
- 视觉视窗:终端设备显示网页的区域。
- 理想视窗:针对当前设备最理想的展示页面的视窗,不会出现横向滚动条,页面刚好全部展现在视窗内,理想视窗即终端屏幕的宽度。
viewport详细设置:
-
通过设置viewport可以设置页面大小,通过meta标签可以设置viewport信息。
-
viewport有以下几个属性:
- width:视口的宽度,正整数或设备宽度device-width(width=device-width)
- height:视口高度,正整数或device-height
- initial-scale(initial-scale=1.0):网页初始缩放值,小数缩小,反之放大(initial-scale=1.0)
- maximum-scale(maximum-scale=1.0):设置页面的最大缩放比例
- minimum-scale(minimum-scale=1.0): 设置页面的最小缩放比例
- user-scaleble(user-scalable=no):用户是否可以缩放
移动端默认会缩放大尺寸的页面的,当我们把上述代码去掉之后,就会随着移动端缩放的比例走,而且还可以自由放大。
1.1.1 解决方案一viewport缩放
方案统计:
-
设置viewport进行缩放
PC端适配移动端可以通过html标签重meta name="viewport"调整视口比例,进行页面缩放。 不过有部分同学使用过程中反应缩放会导致有些页面元素会糊的情况。
代码原理:
- 根据设备屏幕的DPR(设备像素比,比如dpr=2时,表示1个CSS像素由2X2个物理像素点组成) 动态设置 html 的font-size
- 同时根据设备DPR调整页面的缩放值,进而达到高清效果。
作者:Destiny_漂亮的小姐姐 链接:www.jianshu.com/p/07669cb3e... 来源:简书 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
ini
// 仅在移动端时候生效,或者浏览器手机模式
// 整体缩放自适应解决方案(阿里团队高清方案) 淘宝m端使用的解决方案
! function (e) {
function t(a) {
if (i[a]) return i[a].exports;
var n = i[a] = {
exports: {},
id: a,
loaded: !1
};
return e[a].call(n.exports, n, n.exports, t), n.loaded = !0, n.exports
}
var i = {};
return t.m = e, t.c = i, t.p = "", t(0)
}([function (e, t) {
"use strict";
Object.defineProperty(t, "__esModule", {
value: !0
});
var i = window;
t["default"] = i.flex = function (e, t) {
var a = e || 100,
n = t || 1,
r = i.document,
o = navigator.userAgent,
d = o.match(/Android[\S\s]+AppleWebkit/(\d{3})/i),
l = o.match(/U3/((\d+|.){5,})/i),
c = l && parseInt(l[1].split(".").join(""), 10) >= 80,
p = navigator.appVersion.match(/(iphone|ipad|ipod)/gi),
s = i.devicePixelRatio || 1;
p || d && d[1] > 534 || c || (s = 1);
var u = 1 / s,
m = r.querySelector('meta[name="viewport"]');
m || (m = r.createElement("meta"), m.setAttribute("name", "viewport"), r.head.appendChild(m)), m
.setAttribute("content", "width=device-width,user-scalable=no,initial-scale=" + u + ",maximum-scale=" +
u + ",minimum-scale=" + u), r.documentElement.style.fontSize = a / 2 * s * n + "px"
}, e.exports = t["default"]
}]);
flex(100, 1);
// 高清方案默认1rem=100px,那么 btn的宽度就设置为:)
.btn {
width:0.8rem
height:1.2rem
}
- 根据设备屏幕的DPR,自动设置最合适的高清缩放。保证了不同设备下视觉体验的一致性。 旧方案,屏幕越大,元素也越大,新方案,屏幕越大,看到的越多 看得越多的理解: 比如,一篇很长的文章在ip4上,一屏盛不了那么多内容,而在ip6plus上,可以全部看清楚,这是因为,新方案会根据dpr来缩放视口,大屏小屏的手机上,显示的字体大小都是一致的,当然在大屏上看到的东西就多咯~
- 有效解决移动端真实1px问题(这里的1px 是设备屏幕上的物理像素)
1.1.2 解决方案二---两套页面
同时兼任pc和移动适配
通过配置两套不同路由和判断是否是移动端实现
核心代码:router.addRoute(isMobile() ? mobileRoutes[1] : pcRoutes[1]);
(区分路由)
1.1.3 解决方案三---postcss-pxtorem、amfe-flexible
搭配工程化,可以参考第二章【PC端适配方案】
javascript
npm i postcss-pxtorem --save-dev
//使用postcss-pxtorem
module.exports = {
lintOnSave:true,
css:{
loaderOptions:{
postcss:[
require('postcss-pxtorem')({
rootValue:16,//根元素字体大小
unitPrecision:5, //允许rem单位增长的十进制数字
replace:true, //替换包含rems的规则,而不添加后备
mediaQuery:false, //允许在媒体查询中转换px
minPixelValue:0, //设置要替换的最小像素值
selectorBlackList:[], //忽略转换正则匹配项
propList:['*'], //可以从px转换为rem的属性,匹配正则
exclude:/node_modules/i 要忽略并保留为px的文件路径
}),
]
}
}
}
2.PC端适配方案
vue项目使用element-ui框架Rem适配(postcss-pxtorem、amfe-flexible),自动转换px为rem,解决响应式问题
1366 * 768 : 普通液晶显示器 1920 * 1080: 高清液晶显示器 2560 * 1440: 2K高清显示器 4096 * 2160: 4K高清显示器 1280 * 720: 笔记本(1920*1080分辨率下系统默认推荐150%缩放比产生的尺寸)
大屏数据可视化项目通常用于放在电视或广告屏上展示用,而不允许出现滚动条
0. 适配痛点难点
设计稿按照1920*1080的分辨率,16:9的比例设计, 实际开发中,document窗口不足16:9(高度减掉顶部tab及导航栏,地址栏等) 不同分辨率:实际应用场景中,显示场景不同,不能固定写死px单位 不同比例:不同的显示器宽高比与设计稿不一致
1. 什么是rem
rem是CSS3新增的相对长度单位,是指相对于根元素html的font-size计算值的大小。简单可理解为屏幕宽度的百分比。 但是,项目中常见尺寸绘制采用的均是px,要改用rem一时半会缓不过来,而且可能还要换算转换,所以使用rem还是比较麻烦的,但是,我们可以通过插件,能够将项目中的px转换为rem,还可以自定义基数。
2. 安装依赖
kotlin
npm install amfe-flexible // CSS单位自适应转换插件 负责更改根font-size
npm install postcss-pxtorem@^5.1.1 // 如果版本过高可以降版本下载5.1.1版本 负责将px转成rem
javascript
// 用途:echarts字体适配
/**
* echarts字体自适应
* @param {*} font 字号大小
*/
export function echartGetFontSize(font) {
let docEl = document.documentElement,
clientWidth =
window.innerWidth ||
document.documentElement.clientWidth ||
document.body.clientWidth;
if (!clientWidth) return;
let fontSize = clientWidth / 1920;
return font * fontSize;
}
3. 引入amfe-flexible
由于 viewport 单位得到众多浏览器的兼容,lib-flexible 这个过渡方案已经可以放弃使用,不管是现在的版本还是以前的版本,都存有一定的问题。建议大家开始使用 viewport 来替代此方。(待考证?
)
amfe-flexible是lib-flexible的升级版
flexible就是根据不同的屏幕算出html的font-size,通过js来动态写meta标签
实上他做了这几样事情:
- 动态改写
<meta>
标签 - 给
<html>
元素添加data-dpr
属性,并且动态改写data-dpr
的值 - 给
<html>
元素添加font-size
属性,并且动态改写font-size
的值
在main.js中引入amfe-flexible
arduino
import "amfe-flexible"
amfe-flexible 等价代码
javascript
// import '@/utils/rem.js'
// 在utils文件夹下创建rem.js
// 设置 rem 函数
function setRem() {
// 1920 默认大小16px; 1920px = 120rem ;每个元素px基础上/16
const screenWidth = 1920
const scale = screenWidth / 16
const htmlWidth = document.documentElement.clientWidth || document.body.clientWidth
// 得到html的Dom元素
const htmlDom = document.getElementsByTagName('html')[0]
// 设置根元素字体大小
htmlDom.style.fontSize = htmlWidth / scale + 'px'
}
// 初始化
setRem()
// 改变窗口大小时重新设置 rem
window.onresize = function() {
setRem()
}
4. 配置vue.config.js
配置postcss-pxtorem ,可在vue.config.js、postcsssrc.js、postcss.config.js、其中之一配置,权重从左到右降低,没有则新建文件,只需要设置其中一个即可.
javascript
/***
注意点:
(1)rootValue根据设计稿宽度除以10进行设置,这边假设设计稿为1920,即rootValue设为192;
(2)propList是设置需要转换的属性,这边*为所有都进行转换。
***/
module.exports=function(){
devServer:{
port:3000,
open:true
},
//rem配置
css: {
loaderOptions: {
postcss: {
plugins: [
require('postcss-pxtorem')({
rootValue: 192, //根元素字体大小
propList: ['*'], //可以从px转换为rem的属性,匹配正则
// unitPrecision:5, //允许rem单位增长的十进制数字
// replace:true, //替换包含rems的规则,而不添加后备
// mediaQuery:false, //允许在媒体查询中转换px
// minPixelValue:0, //设置要替换的最小像素值
// selectorBlackList:[], //忽略转换正则匹配项
// exclude:/node_modules/i 要忽略并保留为px的文件路径
})
]
}
}
},
}
arduino
// 效果展示 在html上增加根font-size
<html lang="en" style="font-size: 192px;class="light-themes">
5. 总结
5.1 注意事项:
1. 不能使用行内样式
对于行内样式,阿里手淘并不能将px转rem,所以对于需要自适应的样式,如font-size、width、height等请不要写在行内。同理,对于不需要转化的样式可以写在行内,或者使用PX(大写)作为单位。
暂未找到可以转行内rem的插件,可根据下面地址的方式自己实现(未验证是否可行)。blog.csdn.net/weixin_3961...
2. 字号不使用rem
我们都知道chrome的最小显示的字体是12px,如果字体用rem,计算出来小于12px,那么就也会以12px显示,而且我们不希望出现13px或者15px这样的奇葩尺寸,所以字体最好是用PX(大写)来表示,至于适应,我们可以写媒体查询。
css
.item {
border-bottom: 1PX #8d8d8d dashed;
font-size: 12PX;
line-height: 16PX;
@media screen and (min-width: 576PX) {
font-size: 14PX;
line-height: 18PX;
}
@media screen and (min-width: 768PX) {
font-size: 16PX;
line-height: 28PX;
}
@media screen and (min-width: 992PX) {
font-size: 16PX;
line-height: 32PX;
}
@media screen and (min-width: 1200PX) {
font-size: 18PX;
line-height: 64PX;
}
}
PC端响应式媒体断点:
```css
@media (min-width: 1024px){
body{font-size: 18px}
} /*>=1024的设备*/
@media (min-width: 1100px) {
body{font-size: 20px}
} /*>=1100的设备*/
@media (min-width: 1280px) {
body{font-size: 22px;}
} /*>=1280的设备*/
@media (min-width: 1366px) {
body{font-size: 24px;}
}
@media (min-width: 1440px) {
body{font-size: 25px !important;}
}
@media (min-width: 1680px) {
body{font-size: 28px;}
}
@media (min-width: 1920px) {
body{font-size: 33px;}
}
```
5.2 测试反馈:
已测试屏幕尺寸:1920*1080 、1366 * 768
问题:屏幕缩小,网页缩放,效果与原1920*1080不一致
ini
// 仅在移动端时候生效,或者浏览器手机模式
// 整体缩放自适应解决方案(阿里团队高清方案)
! function (e) {
function t(a) {
if (i[a]) return i[a].exports;
var n = i[a] = {
exports: {},
id: a,
loaded: !1
};
return e[a].call(n.exports, n, n.exports, t), n.loaded = !0, n.exports
}
var i = {};
return t.m = e, t.c = i, t.p = "", t(0)
}([function (e, t) {
"use strict";
Object.defineProperty(t, "__esModule", {
value: !0
});
var i = window;
t["default"] = i.flex = function (e, t) {
var a = e || 100,
n = t || 1,
r = i.document,
o = navigator.userAgent,
d = o.match(/Android[\S\s]+AppleWebkit/(\d{3})/i),
l = o.match(/U3/((\d+|.){5,})/i),
c = l && parseInt(l[1].split(".").join(""), 10) >= 80,
p = navigator.appVersion.match(/(iphone|ipad|ipod)/gi),
s = i.devicePixelRatio || 1;
p || d && d[1] > 534 || c || (s = 1);
var u = 1 / s,
m = r.querySelector('meta[name="viewport"]');
m || (m = r.createElement("meta"), m.setAttribute("name", "viewport"), r.head.appendChild(m)), m
.setAttribute("content", "width=device-width,user-scalable=no,initial-scale=" + u + ",maximum-scale=" +
u + ",minimum-scale=" + u), r.documentElement.style.fontSize = a / 2 * s * n + "px"
}, e.exports = t["default"]
}]);
flex(100, 1);
5.3其他问题:
- 如果没效果,查看根元素是否添加上了fongt-size,为添加的话查看css预处理器,如果是sass改成node-sass;我这边使用的版本为:
makefile
"node-sass": "^4.9.0",
"sass-loader": "^7.1.0"
-
大屏改进方案:
- 限制rem的最大值
- 通过媒体查询,限制内容最大宽度
相关文章
【1】 移动端、后台管理、大屏可视化等项目rem适配(postcss-pxtorem、amfe-flexible)。已自测推荐
【3】 amfe-flexible+postcss-px2rem
【4】 移动端布局适配的方案
【6】 手机端页面自适应解决方案---rem布局进阶版(附源码示例)