UniApp 概览
什么是 uni-app?
uni-app 是一个使用 Vue.js 开发所有前端应用的框架,开发者编写一套代码,可发布到iOS、Android、Web(响应式)、以及各种小程序(微信/支付宝/百度/头条/QQ/钉钉/淘宝)、快应用等多个平台。
核心特性
1. 跨平台支持
一套代码,多端运行:
- 移动端应用:iOS App、Android App
- H5网页:响应式移动端网页
- 小程序平台:
- 微信小程序
- 支付宝小程序
- 百度小程序
- 字节跳动小程序(抖音、头条)
- QQ小程序
- 快手小程序
- 京东小程序
- 小红书小程序
- 鸿蒙小程序
- 快应用:华为、联盟快应用
2. Vue 3 生态
- 语法支持:完整支持 Vue 3 Composition API
- 响应式系统:基于 Vue 3 的响应式系统
- 组件化开发:复用 Vue 组件开发经验
- 生态兼容:支持 Vue 生态的部分库
3. 丰富的组件和API
- 内置组件:60+ 跨端组件
- 扩展组件:uni-ui、第三方组件库
- API封装:统一的跨平台API调用方式
- 原生能力:调用各平台原生能力
项目中的 uni-app 版本
版本信息
json
{
"name": "ryplus-uni",
"version": "2.11.0",
"engines": {
"node": ">=18",
"pnpm": ">=7.30"
}
}核心依赖
json
{
"@dcloudio/uni-app": "3.0.0-4060620250520001",
"@dcloudio/uni-components": "3.0.0-4060620250520001",
"@dcloudio/uni-h5": "3.0.0-4060620250520001",
"@dcloudio/uni-mp-weixin": "3.0.0-4060620250520001",
"vue": "^3.4.21",
"pinia": "2.0.36"
}支持的平台
📱 小程序平台
| 平台 | 开发命令 | 构建命令 | 状态 |
|---|---|---|---|
| 微信小程序 | pnpm dev:mp-weixin | pnpm build:mp-weixin | ✅ 主要支持 |
| 支付宝小程序 | pnpm dev:mp-alipay | pnpm build:mp-alipay | ✅ 支持 |
| 百度小程序 | pnpm dev:mp-baidu | pnpm build:mp-baidu | ✅ 支持 |
| 字节跳动小程序 | pnpm dev:mp-toutiao | pnpm build:mp-toutiao | ✅ 支持 |
| QQ小程序 | pnpm dev:mp-qq | pnpm build:mp-qq | ✅ 支持 |
| 快手小程序 | pnpm dev:mp-kuaishou | pnpm build:mp-kuaishou | ✅ 支持 |
| 京东小程序 | pnpm dev:mp-jd | pnpm build:mp-jd | ✅ 支持 |
| 小红书小程序 | pnpm dev:mp-xhs | pnpm build:mp-xhs | ✅ 支持 |
| 飞书小程序 | pnpm dev:mp-lark | pnpm build:mp-lark | ✅ 支持 |
| 鸿蒙小程序 | pnpm dev:mp-harmony | pnpm build:mp-harmony | ✅ 支持 |
🌐 Web 平台
| 平台 | 开发命令 | 构建命令 | 说明 |
|---|---|---|---|
| H5 | pnpm dev:h5 | pnpm build:h5 | 移动端响应式网页 |
📲 App 平台
| 平台 | 开发命令 | 构建命令 | 说明 |
|---|---|---|---|
| App | pnpm dev:app | pnpm build:app | 同时开发 iOS + Android |
| Android | pnpm dev:app-android | pnpm build:app-android | 仅Android |
| iOS | pnpm dev:app-ios | pnpm build:app-ios | 仅iOS |
| 鸿蒙App | pnpm dev:app-harmony | pnpm build:app-harmony | 鸿蒙原生应用 |
⚡ 快应用
| 平台 | 开发命令 | 说明 |
|---|---|---|
| 快应用 | pnpm dev:quickapp-webview | 标准快应用 |
| 华为快应用 | pnpm dev:quickapp-webview-huawei | 华为快应用 |
| 联盟快应用 | pnpm dev:quickapp-webview-union | 快应用联盟 |
项目技术栈
核心框架
- uni-app 3.x:跨平台应用框架
- Vue 3.4+:渐进式 JavaScript 框架
- TypeScript 5.x:JavaScript 的超集
- Vite 6.x:下一代前端构建工具
UI 组件库
- WotUI:自维护重构版本,基于 Vue 3 + TypeScript
- uni-ui:uni-app 官方组件库(按需使用)
工具库
- Pinia:Vue 3 状态管理
- UnoCSS:原子化 CSS 引擎
- VueUse:Vue 组合式工具库(部分功能)
开发工具
- ESLint:代码质量检查
- Prettier:代码格式化
- TypeScript:类型检查
- uni-helper:uni-app 开发增强工具
开发环境要求
Node.js
- 版本要求:Node.js >= 18
- 推荐版本:Node.js 20 LTS
- 版本管理:推荐使用 nvm 管理 Node.js 版本
包管理器
- pnpm >= 7.30(推荐)
- npm >= 8.0(备选)
- yarn >= 1.22(备选)
开发工具
必备工具
VSCode:推荐的代码编辑器
- 安装插件:
- Volar(Vue 3 支持)
- uni-create-view(uni-app 页面创建)
- uni-helper(uni-app 代码提示)
- ESLint
- Prettier
- 安装插件:
微信开发者工具:调试微信小程序
HBuilderX:调试 App(可选)
其他平台工具
- 支付宝开发者工具:调试支付宝小程序
- 百度开发者工具:调试百度小程序
- 抖音开发者工具:调试字节跳动小程序
- QQ开发者工具:调试QQ小程序
快速开始
1. 克隆项目
bash
git clone https://github.com/your-repo/ruoyi-plus-uniapp.git
cd plus-uniapp2. 安装依赖
bash
# 使用 pnpm(推荐)
pnpm install
# 或使用 npm
npm install3. 启动开发
H5 开发
bash
pnpm dev:h5微信小程序开发
bash
pnpm dev:mp-weixin然后:
- 打开微信开发者工具
- 导入项目目录:
dist/dev/mp-weixin - 配置小程序 AppID
App 开发
bash
pnpm dev:app然后:
- 打开 HBuilderX
- 导入项目目录:
dist/dev/app - 连接手机或模拟器运行
4. 生产构建
bash
# H5 构建
pnpm build:h5
# 微信小程序构建
pnpm build:mp-weixin
# App 构建
pnpm build:appuni-app 特色功能
1. 条件编译
针对不同平台编写特定代码:
vue
<template>
<!-- #ifdef MP-WEIXIN -->
<view>仅微信小程序显示</view>
<!-- #endif -->
<!-- #ifdef H5 -->
<view>仅H5显示</view>
<!-- #endif -->
</template>2. 原生渲染
- 小程序:使用小程序原生渲染
- App:使用 Weex 渲染引擎
- H5:使用浏览器渲染
3. 分包加载
优化小程序包体积:
json
{
"pages": [/* 主包页面 */],
"subPackages": [
{
"root": "pages-sub/admin",
"pages": [/* 分包页面 */]
}
]
}4. easycom 自动导入
无需手动导入组件:
vue
<template>
<!-- 自动识别并导入 wd-button -->
<wd-button>按钮</wd-button>
</template>平台差异说明
API 差异
| 功能 | H5 | 小程序 | App |
|---|---|---|---|
| WebSocket | ✅ | ✅ | ✅ |
| SSE | ✅ | ❌ | ✅ |
| DOM操作 | ✅ | ❌ | ❌ |
| BOM对象 | ✅ | 部分 | 部分 |
| 文件系统 | ❌ | ✅ | ✅ |
组件差异
| 组件 | H5 | 小程序 | App | 说明 |
|---|---|---|---|---|
| view | ✅ | ✅ | ✅ | div 标签 |
| scroll-view | ✅ | ✅ | ✅ | 滚动区域 |
| swiper | ✅ | ✅ | ✅ | 轮播组件 |
| video | ✅ | ✅ | ✅ | 视频播放 |
| map | ✅ | ✅ | ✅ | 地图组件 |
| canvas | ✅ | ✅ | ✅ | 画布 |
样式差异
- H5:支持完整的 CSS3
- 小程序:部分 CSS3 特性受限
- App:类似小程序,部分特性受限
学习资源
官方文档
- uni-app 官网:https://uniapp.dcloud.net.cn/
- Vue 3 文档:https://cn.vuejs.org/
- TypeScript 文档:https://www.typescriptlang.org/zh/
社区资源
- uni-app 论坛:https://ask.dcloud.net.cn/
- 插件市场:https://ext.dcloud.net.cn/
- GitHub:https://github.com/dcloudio/uni-app
常见问题
1. 为什么选择 uni-app?
- ✅ 一套代码,多端运行
- ✅ 完整的 Vue 3 生态支持
- ✅ 丰富的组件和 API
- ✅ 活跃的社区和插件市场
- ✅ DCloud 官方技术支持
2. 与原生小程序开发的区别?
| 对比项 | uni-app | 原生小程序 |
|---|---|---|
| 开发语言 | Vue 3 + TypeScript | 小程序专用语法 |
| 跨平台 | ✅ 多端 | ❌ 单一平台 |
| 组件库 | 丰富 | 平台限制 |
| 学习成本 | 低(Vue基础) | 中等 |
| 性能 | 接近原生 | 原生 |
3. uni-app 3.x 与 2.x 的区别?
- 编译器:Vite 替代 Webpack
- Vue 版本:Vue 3 替代 Vue 2
- API:Composition API 支持
- 类型支持:更好的 TypeScript 支持
- 性能:启动和热更新速度提升
4. 开发环境配置问题
问题: 运行 pnpm install 时出错
解决方案:
bash
# 1. 确保 Node.js 版本 >= 18
node -v
# 2. 确保使用 pnpm
npm install -g pnpm
# 3. 清除缓存重新安装
pnpm store prune
rm -rf node_modules
pnpm install问题: 微信开发者工具无法打开项目
解决方案:
- 确保已运行
pnpm dev:mp-weixin - 在微信开发者工具中导入
dist/dev/mp-weixin目录 - 在开发者工具设置中启用"不校验合法域名"
5. 跨平台兼容性问题
问题: 某些功能在特定平台不可用
解决方案: 使用条件编译处理平台差异
vue
<template>
<!-- #ifdef MP-WEIXIN -->
<button open-type="share">分享</button>
<!-- #endif -->
<!-- #ifdef H5 -->
<button @click="handleShare">分享</button>
<!-- #endif -->
</template>
<script lang="ts" setup>
// #ifdef H5
const handleShare = () => {
// H5 分享逻辑
navigator.share?.({
title: '分享标题',
url: window.location.href
})
}
// #endif
</script>6. 性能优化建议
小程序包体积优化:
- 启用分包加载
json
{
"subPackages": [
{
"root": "pages-sub",
"pages": [
{ "path": "detail/index" }
]
}
]
}- 按需引入组件
typescript
// 仅导入需要的组件
import { WdButton, WdIcon } from '@/wd'- 使用 Tree Shaking
typescript
// vite.config.ts
export default defineConfig({
build: {
rollupOptions: {
treeshake: true
}
}
})渲染性能优化:
- 使用虚拟列表处理长列表
vue
<template>
<wd-paging
v-model="list"
:page-size="20"
@load="loadMore"
>
<template #default="{ item }">
<view class="list-item">{{ item.name }}</view>
</template>
</wd-paging>
</template>- 避免不必要的重渲染
vue
<script lang="ts" setup>
import { shallowRef, computed } from 'vue'
// 使用 shallowRef 减少深度响应
const list = shallowRef<Item[]>([])
// 使用 computed 缓存计算结果
const filteredList = computed(() =>
list.value.filter(item => item.active)
)
</script>最佳实践
1. 项目结构组织
推荐的项目目录结构:
src/
├── api/ # API 接口定义
│ ├── modules/ # 按模块分类的 API
│ └── index.ts # API 导出入口
├── components/ # 公共组件
│ ├── business/ # 业务组件
│ └── common/ # 通用组件
├── composables/ # 组合式函数
│ ├── useAuth.ts # 认证相关
│ ├── useHttp.ts # 请求封装
│ └── useModal.ts # 弹窗相关
├── layouts/ # 布局组件
├── pages/ # 主包页面
├── pages-sub/ # 分包页面
├── stores/ # Pinia 状态管理
│ ├── modules/ # 状态模块
│ └── index.ts # Store 导出
├── styles/ # 全局样式
│ ├── variables.scss # SCSS 变量
│ └── index.scss # 全局样式入口
├── types/ # TypeScript 类型
├── utils/ # 工具函数
├── wd/ # WD UI 组件库
├── App.vue # 根组件
├── main.ts # 应用入口
├── manifest.json # 应用配置
├── pages.json # 页面配置
└── uni.scss # uni-app 主题变量2. 组件开发规范
vue
<template>
<view :class="rootClass" :style="customStyle">
<slot />
</view>
</template>
<script lang="ts" setup>
import { computed } from 'vue'
// 1. 定义属性接口
interface Props {
/** 自定义样式 */
customStyle?: string
/** 自定义类名 */
customClass?: string
/** 是否禁用 */
disabled?: boolean
}
// 2. 定义属性默认值
const props = withDefaults(defineProps<Props>(), {
customStyle: '',
customClass: '',
disabled: false
})
// 3. 定义事件
const emit = defineEmits<{
click: [event: Event]
}>()
// 4. 计算属性
const rootClass = computed(() => {
return [
'my-component',
props.customClass,
{ 'is-disabled': props.disabled }
]
})
</script>3. 状态管理规范
typescript
// stores/modules/user.ts
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import type { UserInfo } from '@/types'
export const useUserStore = defineStore('user', () => {
// 状态
const token = ref<string>('')
const userInfo = ref<UserInfo | null>(null)
// 计算属性
const isLoggedIn = computed(() => !!token.value)
const userName = computed(() => userInfo.value?.nickname || '未登录')
// 方法
const setToken = (newToken: string) => {
token.value = newToken
uni.setStorageSync('token', newToken)
}
const setUserInfo = (info: UserInfo) => {
userInfo.value = info
}
const logout = () => {
token.value = ''
userInfo.value = null
uni.removeStorageSync('token')
}
// 初始化
const init = () => {
const savedToken = uni.getStorageSync('token')
if (savedToken) {
token.value = savedToken
}
}
return {
token,
userInfo,
isLoggedIn,
userName,
setToken,
setUserInfo,
logout,
init
}
})4. API 请求封装
typescript
// api/request.ts
import { useUserStore } from '@/stores'
interface RequestConfig {
url: string
method?: 'GET' | 'POST' | 'PUT' | 'DELETE'
data?: Record<string, any>
header?: Record<string, string>
}
interface Response<T = any> {
code: number
msg: string
data: T
}
const BASE_URL = import.meta.env.VITE_API_URL
export const request = <T = any>(config: RequestConfig): Promise<T> => {
const userStore = useUserStore()
return new Promise((resolve, reject) => {
uni.request({
url: `${BASE_URL}${config.url}`,
method: config.method || 'GET',
data: config.data,
header: {
'Content-Type': 'application/json',
'Authorization': userStore.token ? `Bearer ${userStore.token}` : '',
...config.header
},
success: (res) => {
const response = res.data as Response<T>
if (response.code === 200) {
resolve(response.data)
} else if (response.code === 401) {
// Token 过期
userStore.logout()
uni.navigateTo({ url: '/pages/login/index' })
reject(new Error('登录已过期'))
} else {
uni.showToast({
title: response.msg || '请求失败',
icon: 'none'
})
reject(new Error(response.msg))
}
},
fail: (error) => {
uni.showToast({
title: '网络请求失败',
icon: 'none'
})
reject(error)
}
})
})
}5. 条件编译最佳实践
vue
<template>
<view class="container">
<!-- 平台特定的头部 -->
<!-- #ifdef MP-WEIXIN -->
<view class="weixin-header">
<button open-type="getUserInfo" @getuserinfo="onGetUserInfo">
获取用户信息
</button>
</view>
<!-- #endif -->
<!-- #ifdef H5 -->
<view class="h5-header">
<button @click="onLogin">登录</button>
</view>
<!-- #endif -->
<!-- 通用内容 -->
<view class="content">
<slot />
</view>
</view>
</template>
<script lang="ts" setup>
// #ifdef MP-WEIXIN
const onGetUserInfo = (e: any) => {
console.log('微信用户信息:', e.detail)
}
// #endif
// #ifdef H5
const onLogin = () => {
// H5 登录逻辑
}
// #endif
</script>调试技巧
1. H5 调试
bash
# 启动开发服务器
pnpm dev:h5使用浏览器开发者工具进行调试:
- 打开 Chrome DevTools (F12)
- 使用移动设备模拟器测试响应式
- 使用 Network 面板查看请求
- 使用 Console 面板查看日志
2. 微信小程序调试
bash
# 启动小程序编译
pnpm dev:mp-weixin调试步骤:
- 打开微信开发者工具
- 导入
dist/dev/mp-weixin目录 - 使用开发者工具的调试面板
- 查看 AppData 面板了解数据状态
- 使用远程调试功能真机调试
3. 日志输出
typescript
// 使用 uni.log 兼容多平台
const log = {
info: (...args: any[]) => {
// #ifdef H5
console.log(...args)
// #endif
// #ifndef H5
console.log(JSON.stringify(args))
// #endif
},
error: (...args: any[]) => {
console.error(...args)
}
}
// 使用
log.info('用户信息:', userInfo)4. 网络请求调试
typescript
// 开发环境启用请求日志
const DEBUG = import.meta.env.DEV
export const request = async (config: RequestConfig) => {
if (DEBUG) {
console.log('🚀 Request:', config.url, config.data)
}
try {
const response = await doRequest(config)
if (DEBUG) {
console.log('✅ Response:', config.url, response)
}
return response
} catch (error) {
if (DEBUG) {
console.error('❌ Error:', config.url, error)
}
throw error
}
}发布部署
1. H5 部署
bash
# 生产构建
pnpm build:h5
# 输出目录
dist/build/h5/部署到服务器:
bash
# 使用 nginx 配置
server {
listen 80;
server_name your-domain.com;
root /path/to/dist/build/h5;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
}2. 小程序发布
bash
# 生产构建
pnpm build:mp-weixin发布流程:
- 打开微信开发者工具
- 导入
dist/build/mp-weixin目录 - 点击"上传"按钮
- 填写版本号和备注
- 在微信公众平台提交审核
3. App 打包
bash
# 生产构建
pnpm build:app使用 HBuilderX 打包:
- 打开 HBuilderX
- 导入项目
- 发行 → 原生App-云打包
- 配置签名证书
- 等待打包完成
版本升级
升级 uni-app 版本
bash
# 使用官方升级工具
pnpm uvm
# 或手动升级
pnpm add @dcloudio/uni-app@latest升级注意事项
- 备份项目:升级前备份代码和依赖锁文件
- 阅读更新日志:了解 Breaking Changes
- 测试功能:升级后在各平台测试核心功能
- 更新依赖:同步更新相关插件和依赖
