uni-app 知识点总结:从入门到实战的全栈开发指南
前言
uni-app 是 DCloud 推出的跨平台开发框架,基于 Vue.js 实现「一次开发,多端部署」,支持编译到微信小程序、支付宝小程序、H5、App(Android/iOS)等 10+ 平台,代码复用率高达 80%-90%。本文将从基础概念、核心模块、进阶技巧到实战经验,全面解析 uni-app 的核心知识点,适合新手快速入门和进阶开发者查漏补缺。
一、基础核心概念:uni-app 是什么?
1.1 框架定位与核心优势
- 跨平台解决方案:
通过一套代码同时生成多端应用,避免为不同平台重复开发,大幅降低时间和人力成本。 - 技术栈兼容性:
- 前端:基于 Vue.js(支持 Vue 2.x 和 Vue 3.x),兼容 Vue 组件化、响应式数据、生命周期等特性。
- 后端:无绑定,可对接任意服务端(如 Node.js、Java、PHP),通过
uni.request
统一发起网络请求。
- 核心优势:
- 高效开发:官方集成开发工具 HBuilderX,支持真机调试、云端打包、插件市场一键导入。
- 生态丰富:内置 50+ 基础组件,插件市场超 3000+ 开源插件(如支付、地图、IM 等),UI 框架兼容 uView、Vant Weapp 等。
1.2 项目目录结构解析
plaintext
uni-app 项目骨架
├─ pages/ # 页面组件(必选,按端差异化可创建 subPages/ 目录)
│ ├─ index/ # 首页组件(包含 index.vue、json、scss、js)
│ └─ detail/ # 详情页组件
├─ components/ # 自定义组件(全端通用,如公共按钮、表单组件)
├─ static/ # 静态资源(图片、字体、视频等,建议通过 CDN 加速)
├─ uni.config.json # 全局配置(路由、多端差异化配置、插件声明)
├─ manifest.json # 应用清单(App 端权限、图标、小程序 AppID 等)
├─ main.js # 入口文件(全局 JS 逻辑、状态管理库注册,如 Pinia)
├─ App.vue # 应用根组件(应用级生命周期、全局样式、全局事件)
├─ vue.config.js # 项目配置(H5 端 Webpack 配置,如代码拆分、代理)
└─ package.json # 依赖管理(npm/yarn 安装第三方库)
1.3 核心语法:Vue 特性与 uni 专属语法
1.3.1 Vue 兼容性特性
- 组件化开发:
支持components
目录自定义组件,通过props
父子传值,$emit
触发事件,与 Vue 组件写法一致。vue
<!-- 子组件 --> <template> <button @click="$emit('on-click')">点击我</button> </template>
- 响应式数据:
使用data
定义响应式状态,computed
处理派生数据,watch
监听数据变化。 - 生命周期钩子:
钩子函数 触发时机 适用场景 onLoad
页面加载时(接收路由参数) 初始化数据获取(如 options.id
)onShow
页面显示时(切入前台) 刷新页面状态(如更新计数) onReady
页面渲染完成(仅 H5 可操作 DOM) 初始化第三方库(如 echarts) onUnload
页面卸载时(返回上一页) 清理定时器、取消网络请求
1.3.2 uni 专属语法
- 条件编译:按平台拆分代码(语法:
#ifdef 平台标识
/#endif
)vue
<!-- 仅微信小程序显示微信登录按钮 --> #ifdef MP-WEIXIN <button @click="uni.login({ provider: 'weixin' })">微信登录</button> #endif
常用平台标识:平台 标识 示例场景 微信小程序 MP-WEIXIN
调用微信支付接口 H5 H5
加载 Web 端专属 JS 脚本 App(Android/iOS) APP-PLUS
调用设备摄像头 plus.camera
支付宝小程序 MP-ALIPAY
处理支付宝回调通知 - 响应式单位
rpx
:- 1rpx = 1px / 设备像素比,自动适配不同屏幕宽度(如 750rpx 始终等于屏幕宽度,适用于小程序 / 快应用)。
- H5/App 端可混合使用
px
(H5)或dp
(App),通过uni.scss
定义全局单位变量:scss
$font-size-base: 32rpx; /* 对应小程序 28px,App 16dp */
- 路由导航:
- 路由表在
pages.json
中声明(注意页面顺序决定编译后的层级):json
{ "pages": [ { "path": "pages/index/index", "name": "首页" }, { "path": "pages/detail/detail", "name": "详情页" } ] }
- 导航方法对比:
方法 功能描述 对应小程序 API 示例代码 uni.navigateTo
保留当前页,跳转新页面 wx.navigateTo
uni.navigateTo({ url: '/pages/detail/detail' })
uni.redirectTo
关闭当前页,跳转新页面 wx.redirectTo
uni.redirectTo({ url: '/pages/index/index' })
uni.reLaunch
关闭所有页,跳转指定页面 wx.reLaunch
uni.reLaunch({ url: '/pages/login/login' })
uni.navigateBack
返回上一页(可传 delta 层数) wx.navigateBack
uni.navigateBack({ delta: 2 })
(返回两级)
- 路由表在
二、组件与 API 体系:从基础到进阶
2.1 组件系统:内置组件 vs 自定义组件 vs UI 框架
2.1.1 内置组件:多端样式统一
uni-
前缀组件:
官方提供 50+ 基础组件,如uni-button
(按钮)、uni-form
(表单)、uni-list
(列表),自动适配多端样式(如小程序圆角按钮、H5 端直角按钮)。vue
<!-- 多端统一的表单组件 --> <uni-form @submit="onSubmit"> <uni-input name="username" placeholder="用户名"></uni-input> <uni-password name="password" placeholder="密码"></uni-password> <uni-button type="primary" form-type="submit">提交</uni-button> </uni-form>
- 小程序原生组件:
通过mp-
前缀引入(仅小程序端生效),如mp-view
(视图容器)、mp-image
(图片),用于兼容小程序特殊功能。
2.1.2 自定义组件:跨端注意事项
- 写法规范:
与 Vue 组件一致,存放在components/
目录,通过components
选项注册后使用。vue
<!-- 自定义组件:MyButton.vue --> <template> <button :class="type === 'primary' ? 'primary-btn' : 'normal-btn'" @click="$emit('click')"> {{ text }} </button> </template> <script> export default { props: { text: String, type: { type: String, default: 'normal' } } }; </script>
- 跨端差异:
- 小程序不支持动态组件
:is
,需用v-if/v-else
替代。 - 样式默认
scoped
,如需影响子组件,添加deep
选择器:css
/* 穿透样式(仅 H5 有效,小程序需单独适配) */ ::v-deep .child-class { color: red; }
- 小程序不支持动态组件
2.1.3 主流 UI 框架推荐
框架名称 | 特点 | 适用场景 | 集成方式 |
---|---|---|---|
uView | 全端适配(95%+ 组件多端兼容),300+ 组件,含电商、表单、图表等 | 中大型项目、多端一致性需求 | npm install uview-ui + 全局注册 |
ColorUI | 轻量化(体积 < 1MB),主打视觉设计,适合移动端 | 个人博客、展示类项目 | 下载源码后引入 colorui.css |
Vant Weapp | 小程序优先,H5/App 需条件编译适配 | 以小程序为主的电商项目 | npm install vant-weapp + 按需引入 |
2.2 API 分类:网络请求、设备能力、数据存储
2.2.1 网络请求:统一封装与错误处理
- 基础用法:
javascript
// 发起 GET 请求 uni.request({ url: 'https://api.com/user/info', method: 'GET', success: (res) => { console.log(res.data); } });
- Promise 封装(推荐):
javascript
// utils/request.js export function request(url, data = {}, method = 'GET') { return new Promise((resolve, reject) => { uni.request({ url: `https://api.com${url}`, method, data, header: { 'Authorization': `Bearer ${uni.getStorageSync('token')}` }, success: (res) => { if (res.statusCode === 200) resolve(res.data); else reject(new Error('请求失败')); }, fail: (err) => reject(err) }); }); }
2.2.2 设备能力:跨端调用原生功能
- 通用 API:
- 系统信息:
uni.getSystemInfo()
(获取屏幕宽度、设备型号等)。 - 媒体操作:
uni.playVoice({ filePath: 'audio.mp3' })
(播放语音)。 - 位置定位:
uni.getLocation({ type: 'wgs84' })
(获取经纬度,需用户授权)。
- 系统信息:
- App 专属 API:
通过plus
命名空间调用原生能力(需在manifest.json
中配置权限):javascript
// App 端调用摄像头拍照 #ifdef APP-PLUS plus.camera.getCamera(function(camera) { camera.captureImage(function(path) { console.log('拍照路径:', path); }); }); #endif
2.2.3 数据存储:本地存储 vs 全局状态
- 本地存储:
- 同步 / 异步 API:
javascript
// 存储数据(同步) uni.setStorageSync('userInfo', { name: '张三' }); // 读取数据(异步) uni.getStorage({ key: 'userInfo', success: (res) => {} });
- 限制:小程序端存储大小限制 10MB,H5 端使用
localStorage
(无超时,容量约 5-10MB)。
- 同步 / 异步 API:
- 全局状态管理:
- 简单场景:使用
uni.getStorage
+uni.setStorage
实现轻量状态共享。 - 复杂场景:集成 Pinia(Vue3 推荐)或 Vuex,跨端无差异:
javascript
// store/user.js(Pinia Store) import { defineStore } from 'pinia'; export const useUserStore = defineStore('user', { state: () => ({ token: '', userInfo: null }), actions: { setToken(token) { this.token = token; uni.setStorageSync('token', token); // 持久化存储 } } });
- 简单场景:使用
三、跨平台适配:解决多端差异的核心技巧
3.1 条件编译:精准区分各平台代码
- 语法规则:
vue
#ifdef 平台标识 // 仅指定平台编译此代码 平台特有的逻辑(如 API 调用、组件渲染) #endif
- 组合使用场景:
vue
<!-- 微信/支付宝小程序显示对应登录按钮,H5 端显示账号密码登录 --> #ifdef MP-WEIXIN <wechat-login @success="onLogin"></wechat-login> #elif MP-ALIPAY <alipay-login @success="onLogin"></alipay-login> #else <form @submit="onFormLogin"></form> #endif
3.2 样式适配:多端显示一致性处理
3.2.1 单位选择策略
- 小程序 / 快应用:优先使用
rpx
,自动适配屏幕宽度(如 375rpx 对应 iPhone 13 宽度的一半)。 - H5/App:
- H5 端:使用
px
或vw/vh
(视口单位),如width: 100vw
(占满屏幕宽度)。 - App 端:使用
dp
(设备独立像素),通过uni.scss
定义转换变量:scss
$dp-16: 32rpx; /* 16dp 对应 32rpx(假设设备像素比为 2) */
- H5 端:使用
3.2.2 选择器与样式差异
小程序限制:
- 不支持 CSS3 伪类(如
:hover
),:active
需手动添加active
类。 - 不支持
*
通配符,复杂选择器需简化(如用类名替代标签选择器)。
- 不支持 CSS3 伪类(如
- 全局样式:
在App.vue
中定义公共样式,通过@import
引入全局uni.scss
:vue
<style lang="scss"> @import '@/uni.scss'; /* 全局变量与混合宏 */ page { background-color: $bg-color; /* 使用自定义变量 */ font-size: $base-font-size; } </style>
3.3 插件机制:扩展功能的关键
- 官方插件市场:
通过 HBuilderX 内置市场搜索插件(如uni-pay
多端支付插件、uni-share
社会化分享插件),一键导入项目。 - 原生插件开发:
- App 端:使用
uni原生插件
机制,结合 Android Studio 开发.aar
或 Xcode 开发.framework
,实现自定义原生功能(如指纹识别、蓝牙连接)。 - 小程序端:通过微信开放接口(如微信登录、模板消息)或自定义组件(如地图选点组件)实现平台特有功能。
- App 端:使用
四、进阶开发:性能优化、生命周期与混合开发
4.1 生命周期:应用、页面、组件的不同钩子
4.1.1 应用级钩子(App.vue 中声明)
钩子函数 | 触发时机 | 典型用途 |
---|---|---|
onLaunch | 应用初始化时(仅执行一次) | 加载全局配置、初始化登录状态 |
onShow | 应用切前台时(从后台返回) | 更新应用级状态(如未读消息计数) |
onHide | 应用切后台时(按 Home 键) | 暂停定时器、取消长连接请求 |
4.1.2 页面级钩子(页面组件中声明)
javascript
export default {
onLoad(options) {
// 页面加载,获取路由参数(如商品 ID:options.goodsId)
this.getGoodsDetail(options.goodsId);
},
onReady() {
// 页面渲染完成(H5 端可操作 DOM,如初始化 echarts 图表)
#ifdef H5
this.initChart();
#endif
},
onUnload() {
// 页面卸载,清理副作用(如清除定时器、取消订阅)
clearInterval(this.timer);
}
};
4.1.3 组件级钩子
- 与 Vue 组件一致(如
created
、mounted
),但 小程序端不支持mounted
(页面渲染完成通过onReady
处理)。
4.2 性能优化:提升多端运行效率
4.2.1 列表渲染优化
- 长列表场景:
- App/H5 端:使用
uni-virtual-list
虚拟滚动组件(仅渲染可见区域,减少 DOM 节点数)。 - 小程序端:手动实现分页加载,通过
v-for
渲染有限数据,滚动到底部时加载下一页:javascript
// 分页加载逻辑 onReachBottom() { if (!this.isLoading && this.page < this.totalPage) { this.page++; this.loadMoreData(); } }
- App/H5 端:使用
- 避免无意义渲染:
在v-for
中添加唯一:key
,避免 Vue diff 算法误判;复杂表达式提前计算到computed
或method
中。
4.2.2 图片与资源优化
- 使用
uni-image
组件:
支持lazy-load
懒加载(图片进入视口后加载)、mode
自适应模式(如widthFix
保持宽高比):vue
<uni-image src="{{ imgUrl }}" lazy-load mode="widthFix" placeholder="static/loading.png" ></uni-image>
- 压缩与格式转换:
图片上传前通过工具(如 TinyPNG)压缩,优先使用 WebP 格式(体积小、兼容性好);App 端在manifest.json
中开启「图片压缩插件」。
4.2.3 代码拆分与分包
- H5 端:在
vue.config.js
中配置 Webpack 分包,将高频使用的库(如 Vue、uView)拆分为单独文件:javascript
// vue.config.js module.exports = { chainWebpack: (config) => { config.optimization.splitChunks({ chunks: 'all', cacheGroups: { vendor: { name: 'vendor', chunks: 'initial', priority: -10 } } }); } };
- 小程序端:通过
pages.json
的subPackages
配置分包,单包大小不超过 2MB,低频页面(如个人中心)拆分到独立分包:json
{ "subPackages": [ { "root": "subpkg", "pages": ["user/index", "user/setting"] } ] }
4.3 混合开发:原生与 H5 功能结合
- H5 页面嵌入:
通过uni-webview
组件加载外部 H5 页面,支持 JS 交互(如 H5 向 uni-app 传递数据):vue
<!-- 嵌入 H5 页面 --> <uni-webview ref="webview" src="https://h5.example.com" @message="handleWebviewMessage" ></uni-webview>
javascript
// 接收 H5 消息 handleWebviewMessage(e) { const data = e.detail; uni.showToast({ title: `H5 传递数据:${data}` }); }
- App 原生页面跳转:
使用plus.webview
接口调用原生页面(如地图导航、文件管理),需配合原生插件开发:javascript
#ifdef APP-PLUS plus.webview.open('nativePage.html', 'nativePage', { top: '0px', bottom: '0px' }); #endif
五、打包与发布:多端上线全流程
5.1 小程序发布步骤
- 配置 AppID:
在manifest.json
→「微信小程序配置」中填写小程序AppID
(需在微信公众平台注册)。 - 合法域名配置:
登录 微信公众平台 →「开发」→「服务器域名」,添加uni.request
使用的域名(需 HTTPS)。 - 打包与上传:
- HBuilderX 中点击「运行到微信小程序模拟器」,确认无误后点击「发行」→「微信小程序」,生成代码后在微信开发者工具中提交审核。
5.2 App 打包方案
- 云端打包(推荐):
HBuilderX 内置「云打包」功能,实名认证后选择「Android 打包」或「iOS 打包」,自动生成签名证书(适合快速发布)。 - 本地打包:
- Android:配置 Android Studio 环境,生成
.keystore
签名文件,通过gradle
编译生成.apk
。 - iOS:使用 Xcode 生成
.p12
证书,配置manifest.json
中的证书信息,编译生成.ipa
(需 Mac 环境)。
- Android:配置 Android Studio 环境,生成
5.3 H5 部署建议
- 打包后生成
dist
目录,部署到 Nginx / 服务器,或通过 Netlify、Vercel 等平台托管(自动支持 HTTPS 和 CDN 加速)。 - 配置代理解决跨域问题(
vue.config.js
中添加):javascript
module.exports = { devServer: { proxy: { '/api': { target: 'https://api.com', changeOrigin: true, pathRewrite: { '^/api': '' } } } } };
六、学习资源与避坑指南
6.1 官方核心资源
- 文档中心:uni-app 开发文档(API、组件、最佳实践全覆盖)。
- 插件市场:DCloud 插件市场(3000+ 开源插件,含示例代码)。
- 开发工具:HBuilderX 下载(官方 IDE,集成调试、打包、真机运行)。
6.2 社区与案例
- 开发者论坛:DCloud 论坛(提问答疑、实战案例分享,日均活跃用户超 10W)。
- 开源项目:GitHub 搜索
uni-app-template
(如电商模板uni-e-commerce
、后台管理模板uni-admin
)。 - 交流群:微信搜索「uni-app 开发者群」,加入官方技术群获取实时支持(群号:487652345)。
6.3 常见问题避坑
- 样式不生效:
- 检查是否使用了平台不支持的 CSS 特性(如小程序不支持
filter
滤镜)。 - 小程序端样式穿透需使用
deep
选择器:page ::v-deep .class { color: red; }
。
- 检查是否使用了平台不支持的 CSS 特性(如小程序不支持
- API 兼容性问题:
- 调用前通过 兼容性表 确认各端支持情况,如
uni.getLocation
在支付宝小程序需单独申请权限。
- 调用前通过 兼容性表 确认各端支持情况,如
- 打包体积过大:
- 剔除未使用的插件(
manifest.json
中删除无效模块),H5 端开启 Gzip 压缩(服务器配置)。
- 剔除未使用的插件(
通过实战项目(如电商小程序 + H5 + App 三端开发)逐步积累经验,遇到问题优先查阅官方文档和兼容性表,结合社区资源解决难题。uni-app 适合中小项目快速落地,也能通过原生插件扩展支持复杂场景,是跨平台开发的性价比之选。