一、📖 前言
大多数uni-app开发停留在“功能能跑”阶段,导致:
❌ 多端样式错乱
❌ 长列表卡顿、白屏
❌ 小程序审核被拒
❌ 迭代困难、代码崩盘
✅ 本文基于多个商业项目实战,提炼出6大核心模块,可直接作为团队规范 + 面试复习。
二、💡 为什么企业持续选择uni-app?
| 维度 | uni-app | RN / Flutter / Taro |
|---|---|---|
| 多端 | ✅ 小程序+H5+App | ❌ 1–2端 |
| 成本 | ✅ Vue3 → 零学习 | ❌ 新框架 |
| 性能 | ✅ Web + Nvue双引擎 | ❌ 单一渲染 |
| 生态 | ✅ 成熟稳定 | ⚠️ 参差不齐 |
一句话:一套代码,真全端,低成本,可上线。
三、🔍 底层架构(面试必问)
核心:编译时 + 运行时混合架构
text
Vue源码 → 编译阶段 → 各端原生代码 ↓ 小程序(WXML) / H5(DOM) / App(原生)
❌ 不是运行时解析(无性能损耗)
✅ 各端原生适配,兼容性更强
双引擎策略(App关键)
| 引擎 | 场景 | 效果 |
|---|---|---|
| Web渲染 | 表单、详情、个人中心 | 快速迭代 |
| Nvue原生 | 长列表、瀑布流、动画 | 60fps 流畅 |
四、📁 工程化规范(团队必备)
技术栈(2026标准)
js
Vue3 + Vite + Pinia // 全面淘汰 Vue2 + Webpack + Vuex
目录结构(直接套用)
text
src/ ├── pages/ # 页面(模块化) ├── components/ # 全局组件 ├── utils/ # 请求 + 工具 ├── store/ # Pinia └── uni.scss # 全局样式
五、🛠️ 全局封装(复制即用)
5.1 请求拦截(统一Token + 401处理)
js
// utils/request.js const BASE_URL = 'https://api.example.com' export const request = (options) => { return new Promise((resolve, reject) => { const token = uni.getStorageSync('token') uni.request({ url: BASE_URL + options.url, method: options.method || 'GET', header: { 'Authorization': token ? `Bearer ${token}` : '', 'Content-Type': 'application/json' }, success(res) { if (res.statusCode === 401) { uni.removeStorageSync('token') uni.reLaunch({ url: '/pages/login/login' }) reject('登录过期') } else if (res.statusCode === 200) { resolve(res.data) } else { uni.showToast({ title: '请求失败', icon: 'none' }) reject(res) } }, fail() { uni.showToast({ title: '网络异常', icon: 'none' }) reject() } }) }) }5.2 Pinia持久化(解决Token丢失)
js
// store/user.js export const useUserStore = defineStore('user', { state: () => ({ token: '', userInfo: null }), actions: { async login(data) { const res = await request({ url: '/login', method: 'POST', data }) this.token = res.token this.userInfo = res.userInfo uni.setStorageSync('token', res.token) }, logout() { this.token = '' this.userInfo = null uni.removeStorageSync('token') } } })六、🎯 多端适配(根治兼容Bug)
条件编译(精准隔离)
vue
<!-- 微信专有 --> <!-- #ifdef MP-WEIXIN --> <button open-type="getUserInfo">微信登录</button> <!-- #endif --> <!-- App专有 --> <!-- #ifdef APP-PLUS --> <button @click="scanQRCode">扫一扫</button> <!-- #endif -->
样式铁律(避免90%样式问题)
| 规范 | 要求 | 原因 |
|---|---|---|
| 单位 | 强制rpx | 全机型适配 |
| 全局样式 | 写在uni.scss | 穿透scoped |
| 组件样式 | 不用scoped | 子组件可控 |
跳转规范(最容易翻车)
js
// ✅ tabBar页面 uni.switchTab({ url: '/pages/home/home' }) // ✅ 普通页面 uni.navigateTo({ url: '/pages/detail/detail' }) // ❌ 致命错误 uni.navigateTo({ url: '/pages/home/home' }) // 页面卡死七、⚙️ 性能优化
7.1 首屏3秒优化
| 优化点 | 方案 | 效果 |
|---|---|---|
| 分包 | 主包仅放首页+tabBar | 体积↓60% |
| 图片 | 全量WebP | 体积↓50% |
| 组件 | 按需引入 | 减少冗余 |
7.2 长列表 → 虚拟滚动
vue
<!-- 传统:全量渲染 → 卡顿 --> <!-- 优化:虚拟列表 + 分页 → 60fps --> <recycle-list :list="dataList"> ... </recycle-list>
7.3 App端终极方案:Nvue
复杂列表 / 瀑布流 / 动画 → 改用
.nvue效果:40fps → 60fps
7.4 打包压缩
bash
npm run build -- --minimize # 自动:删除console + 代码压缩 + 去source-map
八、⚠️ 高频坑点(线上血泪史)
| 坑 | 原因 | 秒杀方案 |
|---|---|---|
| 样式穿透失效 | scoped隔离 | 样式放uni.scss |
| Token偶现丢失 | setStorageSync异步 | 加await |
| tabBar跳转空白 | 误用navigateTo | 统一switchTab |
| 审核被拒 | 主包>2MB / 不安全API | 分包 / 删除eval |
九、✅ 上线前终极自检清单
主包 ≤ 2MB
所有图片 → WebP
长列表已虚拟滚动/分页
请求拦截已封装
Token存储加了
awaittabBar全用
switchTab多端差异已条件编译
App复杂页面评估了Nvue
十、📝 总结(一句话+行动)
规范 + 封装 + 适配 + 优化 + 避坑 = 可上线商业项目
🔔如果本文帮你少加一次班,欢迎点赞 + 收藏 + 转发