需求
开发一个平台,要求在PC端和移动端上都有较好的体验。
思路
做到移动端和PC端同时适配,一般有两个大思路:
- 一套资源,根据判断是否是移动设备而选择加载不同的css。
- 两套资源,pc和mobile各一套,分开维护,在入口处进入不同的路由。
两种方式的差别体现在,前者是样式层面分为pc和mobile,后者是页面分为pc和mobile
两个做法各自的特点:
1.前者适用于两端交互和布局差别不大,交互比较简单的项目。只有一套资源,代码量少,维护起来比较简单。
2.后者则适用于两端交互方式和布局差别大,对设计要求高,拓展性要求高的项目。两套资源,代码量大,前期配置比较复杂,但是两端不相互影响,开发起来不用考虑太多。
解决方案
一套资源方案
由于目前项目要求快速开发快速落地,且两端设计稿布局差距不大。所以采用了第一种方式。实现如下:
步骤
1.判断终端设备类型。
main.js中配置,在页面加载前,判断终端设备类型。
navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i)
2.拆分两套css文件。
pc采用px为单位,mobile采用rem和vw结合,并在mobile的css文件中,设置项目font-size,例如设计稿为375px的情况下,html {font-size: calc(100vw/37.5)}
这时候,当移动设备可视窗口大小为375px时,html的font-size为10px,则1rem=10px。
styles结构如下:将css拆分为pc和mobile两套,每个开发人员都有自己的两套css文件。
// mobile.scss
@import './mobile/hm-mobile.scss';
@import './mobile/tf-mobile.scss';
.no-mobile {
display: none;
}
html {
font-size: calc(100vw/37.5);
}
// pc.scss
@import './pc/hm-pc.scss';
@import './pc/tf-pc.scss';
.no-pc {
display: none;
}
3.加载两套css文件
通过判断终端类型,加载不同的css文件,
// main.js配置
import { _isMobile } from '@/utils/utils';
...
...
...
if (_isMobile()) {
require('./styles/mobile.scss');
console.log('mobile');
} else {
console.log('pc');
require('./styles/pc.scss');
}
需****格外注意的是,样式都写在了全局的样式文件里,在多人协同开发时,需要强调命名规范,以防命名污染,可以参考**BEM命名规范 **
为什么不使用媒体查询,靠一套CSS同时搞定PC和移动端? 作者考虑到同一套CSS会使得耦合性太高,后期两端维护起来很麻烦,并且若两端项目都要拆分起来成本增加。因此,可以在两套CSS的前提下,针对其中一端,进行响应式实现,比如针对PC端可做大中小屏的响应式,而不是直接从pc横跨到移动端的响应式。
两套资源方案
基于两套资源的思想,具体怎么实现其实有很多方法,
- 来自网友(配置两端分开)
- 这几天自己做项目使用的一套方案:
步骤
1.限制路由的规范(路由守卫的依据)
2.路由守卫
通过meta的type来对跳转的页面进行拦截,防止直接输入网址造成的跨端访问,当进行跨端访问时,强制拦截,跳转到属于本端类型的相同页面。比如当用手机访问p_index时,跳转到m_index,因此不但meta要设置,两端的页面路由也要保证有一定的规律。这里可做可不做,可以只是拦截跳转到本端首页就可以了。
3.按端类型动态添加网页meta和使用三方插件
// main.js
if (/Android|webOS|iPhone|iPod|BlackBerry|iPad/i.test(navigator.userAgent)) {
Vue.use(VueTouch, { name: 'v-touch' });
VueTouch.config.swipe = {
threshold: 50
};
var oMeta = document.createElement('meta');
oMeta.content = 'width=device-width, initial-scale=1.0, maximum-scale=1.0,minimum-scale=1.0, user-scalable=0';
oMeta.name = 'viewport';
document.getElementsByTagName('head')[0].appendChild(oMeta);
}
4.postcss-pxtorem排除影响
由于项目需要,pc和移动都使用rem开发,都使用了px转rem的插件,但px转rem的转换基数在两端是不同的,需要排除两端的相互影响。
//vue.config.js
const config = {
// ...
css: {
extract: true,
loaderOptions: {
postcss: {
plugins: [
require('postcss-pxtorem')({
rootValue: 192,
exclude: /node_modules\/vant|mobile/i, // 排除mobile和vant库
propList: ['*'],
selectorBlackList: ['.van-'] // 排除移动端使用了vant库
}),
require('postcss-pxtorem')({
rootValue: 37.5,
exclude: 'pc', // 排除pc
propList: ['*']
})
]
}
}
}
};
module.exports = config;