跳转至

🟢 Vue3 移动端 0-1 落地(技术选型 · 搭建 · 兼容 · 对标大厂)

用 Vue3 从零做一个生产级移动端项目。本篇给技术选型方案、项目搭建步骤、兼容性处理、注意事项,并对标大厂主流方案(字节/美团/滴滴等移动端实践)。依据 Vue3 官方文档ViteVantPinia、社区大厂实践沉淀。

适用:要落地 Vue3 移动端项目的开发者。前置:移动端基础适配方案兼容性性能专项


一、技术选型方案(Vue3 移动端主流栈)

选型 为什么
框架 Vue3 + <script setup> 组合式 API、响应式细粒度、TS 友好
构建 Vite 秒级启动、ESM 原生、HMR 快
语言 TypeScript 大厂标配,类型安全
UI 组件库 Vant 4(移动端首选) 59+ 移动组件、按需引入、主题定制
状态 Pinia Vue3 官方推荐,比 Vuex 轻
路由 Vue Router 4(hash 模式优先,Hybrid 友好) hash 兼容 WebView/分享
请求 Axios + 拦截器(或 vue-request 取消/重试/缓存
样式 PostCSS px-to-viewport + SCSS 设计稿 px 自动转 vw
适配 vw + clamp + 容器查询 + viewport-fit=cover 适配
包管理 pnpm 快、省磁盘、严格依赖
移动端增强 vant + @vant/touch-emulator(桌面调试触摸)

大厂对照

  • 字节/美团:Vue3 + Vite + TypeScript + 自研组件库(或 Vant 二开)+ pnpm monorepo。
  • 滴滴:Vue3 + Vant + 自研桥(见 Hybrid)。
  • 共同点:TypeScript 全量、Vite 构建、组件库二开、严格 code review、CI 卡构建体积

二、项目搭建(从 0 到跑起来)

2.1 初始化

# 用官方脚手架
npm create vue@latest my-mobile -- --ts --router --pinia
cd my-mobile && pnpm i

2.2 引入 Vant(按需)

pnpm add vant
pnpm add -D unplugin-vue-components unplugin-auto-import
// vite.config.ts
import Components from 'unplugin-vue-components/vite'
import { VantResolver } from 'unplugin-vue-components/resolvers'
export default defineConfig({
  plugins: [vue(), Components({ resolvers: [VantResolver()] })]  // 自动按需引入 Vant
})
<!-- 直接用,无需 import -->
<template><van-button type="primary">按钮</van-button></template>

2.3 适配配置(PostCSS 自动转 vw)

// postcss.config.cjs
module.exports = {
  plugins: {
    'postcss-px-to-viewport-8-plugin': {
      viewportWidth: 375,         // 设计稿宽
      unitToConvert: 'px',
      propList: ['*'],
      selectorBlackList: ['.ignore', 'van-'],  // Vant 自带适配,别二次转
      minPixelValue: 1
    }
  }
}

坑 1:Vant 组件被二次转 vw 导致尺寸错

Vant 默认按 375 设计且自带 rem/vw 适配,PostCSS 再转会翻倍。把 van- 加黑名单(黑名单,不是白名单),或统一用 Vant 的 rootValue 方案。

2.4 设计稿规范与单位转换(写 px,插件自动转)

核心约定:开发时直接按设计稿写 px,由 PostCSS 插件在构建期自动转成 vw,不要人工算 vw/rem。

1)设计稿规范(团队对齐)

要求
基准宽度 375px(iPhone 标准,Vant 默认基准)
标注单位 设计稿用 px 标注,开发原样写 px
倍率 @2x / @3x 切图由设计导出,开发不手动除 2
字号下限 最小 20px 起标,避免小屏糊字(iOS 最小可读)
1px 边框 用 Vant hairline 或伪元素 scale不要写 0.5px(部分机型不支持)
安全区 底部 TabBar / 固定栏预留 env(safe-area-inset-bottom)
间距栅格 统一 4px 基线(4/8/12/16/24…),保证节奏一致

2)单位转换插件与职责

插件 作用 何时用
postcss-px-to-viewport-8-plugin px → vw(按 viewportWidth:375 主力,业务 px 自动转
postcss-pxtorem + amfe-flexible px → rem(动态根字号) 需要兼容老安卓 WebView 时
autoprefixer 自动加厂商前缀 必备
postcss-px-to-viewportselectorBlackList 跳过 Vant 组件类(van- 防二次转换

3)开发注意事项

  • 只写 px,别手算 vw/remwidth: 100px(设计稿量多少写多少),插件转 vw;手算易错且和插件叠加翻倍。
  • Vant 组件不转selectorBlackList: ['van-'],否则 Vant 自带适配被二次转 → 尺寸翻倍(见坑 1)。
  • 不该转的border-width: 1px 想保留物理 1px 时,把对应类加黑名单;或用 hairline
  • 媒体查询 / 动画里的 pxpropList 默认 ['*'] 会转,若某属性不想转用 ['*', '!border*'] 或加 mediaQuery: false
  • 大屏 / 平板:用 max-vw 或容器查询限制最大宽度,避免无限放大(见 适配方案)。
// postcss.config.cjs —— 写 px,自动转 vw
module.exports = {
  plugins: {
    'postcss-px-to-viewport-8-plugin': {
      viewportWidth: 375,         // 设计稿基准宽
      unitToConvert: 'px',
      propList: ['*'],
      selectorBlackList: ['van-', 'ignore-'],  // 黑名单:Vant 与 .ignore- 不转
      mediaQuery: false,          // 媒体查询里的 px 不转
      minPixelValue: 1
    },
    autoprefixer: {}
  }
}

写代码的心智模型

你眼里只有 375 设计稿的 px;vw、rem、安全区、黑名单全是构建期的"翻译层",开发时不用管。

2.5 viewport meta + 安全区

<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
/* 全局安全区 */
#app { padding-bottom: env(safe-area-inset-bottom); }


三、目录结构(推荐)

src/
├─ api/          # 接口层(axios 实例 + 各模块)
├─ components/   # 业务组件
├─ composables/  # 组合式函数(useXxx)
├─ router/       # 路由 + 守卫
├─ stores/       # Pinia
├─ utils/        # 工具(bridge、request、format)
├─ views/        # 页面
├─ styles/       # 全局样式 + 变量
└─ App.vue

composables 复用逻辑

把"下拉刷新、上拉加载、桥调用、权限"封装成 usePullRefreshuseBridge,页面只调不写重复逻辑。


四、路由与 Hybrid(hash 模式)

// router/index.ts —— Hybrid 用 hash 更稳
const router = createRouter({ history: createWebHashHistory(), routes })

坑 2:history 模式在 WebView 分享后 404

微信分享会改写 URL、刷新后服务端无对应路由 → 白屏。Hybrid/分享场景用 hash 模式(见 兼容性 §八)。


五、兼容性注意事项(Vue3 专项)

注意
1px 边框 用 Vant 的 hairline 或自定义(basics §2.2
100vh 100dvh,Vant 弹层已处理
长列表 vue-virtual-scroller 或 Vant List 无限滚动
组件卸载清理 onUnmounted 清定时器/Observer/Worker(性能 §五
iOS 点击延迟 touch-action: manipulation(Vant 已处理大部分)
低版本 WebView @vitejs/plugin-legacy 出兼容包 + browserslist
// vite.config.ts 兼容老安卓
import legacy from '@vitejs/plugin-legacy'
plugins: [legacy({ targets: ['defaults', 'not IE 11'] })]

六、性能落地(Vue3 专项)

  • 路由懒加载component: () => import('@/views/Home.vue')
  • v-memo / shallowRef:长列表大对象避免深度响应
  • 图片懒加载:Vant Lazyload 或原生 loading="lazy"
  • 首屏骨架:Vant Skeleton
  • 分包build.rollupOptions.output.manualChunks 拆 vendor

坑 3:响应式大数组拖垮渲染

上万条数据别直接 reactive,用 shallowRef + 手动触发,配合虚拟滚动。


七、对标大厂:生产级 Checklist

  • TypeScript 全量 + strict
  • pnpm + monorepo(多端复用)
  • 组件库二开(主题/规范统一)
  • 路由级懒加载 + 拆包,首屏 JS < 200KB(gzip)
  • 适配 vw + 安全区 + 折叠屏容器查询
  • 错误监控(Sentry)+ 性能监控(Web Vitals)
  • CI 卡体积/单测,禁止大依赖入库
  • Hybrid 桥安全(白名单 + 超时,见 debug-hybrid
  • 离线方案(PWA 或离线包,见 pwa

八、面试怎么讲(Vue3 移动端)

面试难点与亮点。 - 难点:折叠屏展开态旧断点错乱 → 容器查询 + ResizeObserver 重排。 - 亮点:搭的 Vue3 移动端脚手架(Vant 二开 + vw 适配 + 桥安全)被 5 个业务复用。