一、前言
随着Nuxtjs被广大开发者运用在实际项目中,如何在同一项目中将PC端和移动端集成在一套代
码体系中, 这是在最近思考的一个问题。
机缘巧合看到一篇技术文章->Nuxt3优雅地在一个项目中集成pc端、移动端多套页面,有感于
此文,直接动手Coding, 搭建一个开箱即用的代码模板(暂不涉及后端)。
二、基本要求
代码模板应满足以下基本要求:
基于Nuxt3,可以集成常见的技术框架,如Element-plus, VantUi等;
代码统一部署,同一访问路径,不同终端加载不同页面资源;
PC端和移动端对应的资源、代码独立分开, 互不影响;
移动端需要适配不同屏幕宽度,并且不影响PC端;
三, 对应方案
要求1:
基于Nuxt3,可以集成常见的技术框架,如Element-plus, VantUi等;
解决方案:
在项目直接下载安装Nuxt3, 可参考:www.nuxtjs.cn/guide/insta…
Nuxt配置Element-plus, 可参考: element-plus.org/zh-CN/guide…
Nuxt配置Vant, 可参考: vant-ui.github.io/vant/#/zh-C…
其他技术框架,可参考其官方文档。
要求2:
代码统一部署,同一访问路径,不同终端加载不同页面资源;
解决方案:
配置Nuxt3, 配置自定义路由表, 在app/router.options.ts, 根据不同终端,返回不同路由 资源。
关键代码:
routers/index.ts
/* routers/index.ts */
/* 公共路由 */
const commonRouters = [ { path: '/', redirect: '/index' }]
/* 注意 PC 与 Mobile 的路由的Path name 须保持一致 */
/* PC */
const PC_Routers = [
{
name: 'index',
path: '/index',
component: () => import('../PC/views/index.vue')
}
]
/* Mobile */
const Mobile_Routers = [
{
name: 'index',
path: '/index',
component: () => import('../mobile/views/index.vue')
}
]
export default {
PC: [ ...PC_Routers, ...commonRouters ],
mobile: [ ...Mobile_Routers, ...commonRouters ]
}
app/router.options.ts
import type { RouterConfig } from '@nuxt/schema'
import routersMap from '~/routers/index'
import { getDeviceType } from '~/utils/index'
/* 根据终端,返回不同路由资源 */
export default <RouterConfig> {
routes: (_routes) => {
const deviceType = getDeviceType() // pc mobile
console.log('终端', deviceType.value)
return routersMap[deviceType.value] ?? routersMap.PC
}
}
utils/index.ts
import { ref } from 'vue'
/* 判断终端是 PC or mobile 参考 https://juejin.cn/post/7326268915100794906 */
export const getDeviceType = () => {
let UA: string
if (process.client) // 如果是在客户端执行,则通过 navigator 获取 user-agent
UA = navigator.userAgent
else // 如果是在服务端执行,则通过请求头获取 user-agent
UA = useRequestHeader('user-agent') as string const type = ref<'mobile' | 'pc'>('pc') // 通过 UA 来判断设备类型是 pc 还是 mobile
if (/(Android|webOS|iPhone|iPod|tablet|BlackBerry|Mobile)/i.test(UA))
type.value = 'mobile'
else
type.value = 'pc'
return type}
要求3:
PC端和移动端对应的资源、代码独立分开, 互不影响;
解决方案:
根据终端的不同,加载不同的入口文件。如
PC: /PC/layout.vue;
mobile: /mobile/layout.vue;
PC端,移动端的对应的资源分别放在PC文件,mobile文件下。
关键代码:
app.vue
<template>
<!-- PC -->
<PCLayout v-if="deviceType === 'pc'"></PCLayout>
<!-- mobile -->
<MobileLayout v-if="deviceType === 'mobile'"></MobileLayout>
</template>
<script lang="ts" setup>
import PCLayout from './PC/layout.vue'
import MobileLayout from './mobile/layout.vue'
import { getDeviceType } from '~/utils/index'
import '~/styles/common.css'
const deviceType = getDeviceType()
</script>
<style lang="scss"></style>
PC/layout.vue
<template>
<div class="cmk-pc-warp">
<NuxtLayout>
<el-config-provider :locale="zhCn">
<NuxtPage />
</el-config-provider>
</NuxtLayout>
</div>
</template>
<script lang="ts" setup>
/* element-plus 使用中文 */
import zhCn from 'element-plus/es/locale/lang/zh-cn'
</script>
<!-- 不使用 scoped -->
<style lang="scss">
/* PC端的公共样式必须包裹在 .cmk-pc-warp */
@use './style/base.scss';
</style>
mobile/layout.vue
<template>
<div class="cmk-mobile-warp">
<NuxtLayout>
<NuxtPage />
</NuxtLayout>
</div>
</template>
<script lang="ts" setup>
/* vant Ui */
import 'vant/lib/index.css';
</script>
<!-- 不使用 scoped -->
<style lang="scss" >
/* 移动端的公共样式必须包裹在 .cmk-mobile-warp */
@use './style/base.scss';
</style>
要求4:
移动端需要适配不同屏幕宽度,并且不影响PC端
解决方案:
移动端端适配, 使用 postcss-pxtorem ,lib-flexible;
- postcss-pxtorem 是一款 PostCSS 插件,用于将 px 单位转化为 rem 单位
- lib-flexible 用于设置 rem 基准值
为了不影响到PC端的代码,需要配置nuxt.config.ts,如下
postcss: {
plugins: {
'postcss-pxtorem': {
rootValue({ file = '' }) {
return file.indexOf('vant') !== -1 ? 37.5 : 75;
},
propList: ['*'],
mediaQuery: false,
exclude: (file = '') => {
// 只对 移动端的 /mobile/、vantUi 文件夹中的文件进行 px 转 rem,其他文件不转换
const needRemArr = ['/mobile/', 'vant']
const bl = needRemArr.find(item => file?.includes(item))
if (bl) return false
return true;
}
},
}
}
到此, 很好地满足上述基本要求。但还有以下不足:
1,PC端,移动端虽然在项目代码地角度已独立,但集成时,各自使用地框架,资源还是集成在一起。因此,项目过大的话,打包后的代码可能会过大,但是由于Nuxt3的SSR(服务器渲染),问题不大。
2, 各终端的公共样式,需要考虑样式最终打包在一起,因此要在最上层加于区分。
3,该模板适合,PC端与移动端的业务相似度比较高,如果各自差异较大,还是不集成更好。
四, 展示效果
完整代码 github:nuxt3-pc-mobile-template
项目部分结构:
PC端 /index 页面
移动端 /index 页面