最近在负责国家物联网标识管理公共服务平台官网 的重构,采用了nuxt.js。那么这次重构除了用nuxt.js,还要做到pc端和移动端的自适应设计。自适应设计暂时想到三种方式:
- 不同端(pc和mobile)映射到不同域名,举个例子:pc端访问的是
www.baidu.com,换到移动端就改为www.m.baidu.com了。但是,这样就要有两个不同项目,若要维护两个项目也是挺麻烦的。毕竟这只是官网,只是一些元素上变化。而不像微博,知乎变化太大。
- css媒体查询
@media。我纠结了很久到底要不要这样…结果还是放弃了。其实看起来很美好,其实开发起来是很痛苦了,做不到完美。一个页面可能很多元素需要改动。而且,移动端用的是流动布局,pc端暂时不考虑响应式就好了。
- 页面启动前根据ua跳转不同路由,pc端访问的是/about,换到移动端跳去 ‘/m/about’。其实跟第一种方法有点类似,但是动用的资源就一个好了,不需要nginx。
最后,我还是采用了第三种方式去进行。(如果有更好的请在留言区告诉我哦,谢谢)
准备好sass配置
- 安装node-sass和sass-loader
- 安装nuxt-sass-resources-loader
之前也说过,怎么把全局变量,函数以及mixins放到全局不需要每个.vue里引入的方法,请参考:这里
根据ua判断给<html>加上属性
判断ua,作为公共方法(写入utils/utils.js)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| export const pcOrMobile = (u) => { let browser = { trident: u.indexOf('Trident') > -1, presto: u.indexOf('Presto') > -1, webKit: u.indexOf('AppleWebKit') > -1, gecko: u.indexOf('Gecko') > -1 && u.indexOf('KHTML') == -1, mobile: !!u.match(/AppleWebKit.*Mobile.*/), ios: !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/), android: u.indexOf('Android') > -1 || u.indexOf('Linux') > -1, iPhone: u.indexOf('iPhone') > -1, iPad: u.indexOf('iPad') > -1, webApp: u.indexOf('Safari') == -1 }; if (browser.mobile || browser.ios || browser.android || browser.iPhone || browser.iPad) { return 'mobile' } else { return 'pc' } }
|
plugins加上devide.js
这里的目的只是根据ua给html加上属性(mobile还是pc)。或者,到时候如果要求PC端也要做自适应还是可以在此处做文章
1) 在plugins里新建devide.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| (function(doc, win) { let docEl = doc.documentElement let resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize' let recalc = function() { if (pcOrMobile(window.navigator.userAgent) === 'pc') { docEl.setAttribute('pc', '') docEl.removeAttribute('mobile', '') } else { docEl.setAttribute('mobile', '') docEl.removeAttribute('pc', '') } } if (!doc.addEventListener) { return } win.addEventListener(resizeEvt, recalc, false) doc.addEventListener('DOMContentLoaded', recalc, false) })(document, window)
|
如果是移动端,那就<html mobile></html>;否则,是pc端就变成<html pc></html>
2) nuxt.config.js修改
1 2 3 4 5 6 7 8
| module.exports={ plugins: [ { src: '~plugins/rem.js', ssr: false } ] }
|
移动端:采用vw,vh作为单位
采用的方案就是用凹凸实验室的利用视口单位实现适配布局rem+vw这个方案作为移动端自适应方案。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| // rem 单位换算:定为 75px 只是方便运算,750px-75px、640-64px、1080px-108px,如此类推 $vw_fontsize: 75; // iPhone 6尺寸的根元素大小基准值 // 根元素大小使用 vw 单位 $vw_design: 750;
html[mobile] { font-size: ($vw_fontsize / ($vw_design / 2)) * 100vw; // 同时,通过Media Queries 限制根元素最大最小值 @media screen and (max-width: 320px) { font-size: 64px; } @media (max-width: 1024px) and (min-width: 540px) { font-size: 108px; } } @function rem($px) { @return ($px / $vw_fontsize) * 1rem; } // body 也增加最大最小宽度限制,避免默认100%宽度的 block 元素跟随 body 而过大过小
body { max-width: 540px; min-width: 320px; }
|
html[mobile]这里的目的就明确了,通过rem.js判断
pc端:采用px作为单位
暂时不对pc端做自适应设计
不同端不同布局(Layout)
pc端和移动端是不一样的布局,那么我针对不同的端有不同的布局:

开发移动端页面的时候,只需要在相应的.vue写上layout:mobile即可。

访问主页根据ua跳转
page的文件夹结构是:

移动端的页面放在pages/m文件夹里,所以移动端访问网页的路由是:’/m/…’
那么,如何使得如果是移动端访问就跳转?
在index.vue入口里加入:
1 2 3 4 5 6 7 8 9
| asyncData({ req, redirect }) { let type = pcOrMobile(req.headers['user-agent']) if (type === 'mobile') { redirect('/m') } }
|