Skip to content

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-weixinpnpm build:mp-weixin✅ 主要支持
支付宝小程序pnpm dev:mp-alipaypnpm build:mp-alipay✅ 支持
百度小程序pnpm dev:mp-baidupnpm build:mp-baidu✅ 支持
字节跳动小程序pnpm dev:mp-toutiaopnpm build:mp-toutiao✅ 支持
QQ小程序pnpm dev:mp-qqpnpm build:mp-qq✅ 支持
快手小程序pnpm dev:mp-kuaishoupnpm build:mp-kuaishou✅ 支持
京东小程序pnpm dev:mp-jdpnpm build:mp-jd✅ 支持
小红书小程序pnpm dev:mp-xhspnpm build:mp-xhs✅ 支持
飞书小程序pnpm dev:mp-larkpnpm build:mp-lark✅ 支持
鸿蒙小程序pnpm dev:mp-harmonypnpm build:mp-harmony✅ 支持

🌐 Web 平台

平台开发命令构建命令说明
H5pnpm dev:h5pnpm build:h5移动端响应式网页

📲 App 平台

平台开发命令构建命令说明
Apppnpm dev:apppnpm build:app同时开发 iOS + Android
Androidpnpm dev:app-androidpnpm build:app-android仅Android
iOSpnpm dev:app-iospnpm build:app-ios仅iOS
鸿蒙Apppnpm dev:app-harmonypnpm 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(备选)

开发工具

必备工具

  1. VSCode:推荐的代码编辑器

    • 安装插件:
      • Volar(Vue 3 支持)
      • uni-create-view(uni-app 页面创建)
      • uni-helper(uni-app 代码提示)
      • ESLint
      • Prettier
  2. 微信开发者工具:调试微信小程序

  3. HBuilderX:调试 App(可选)

其他平台工具

  • 支付宝开发者工具:调试支付宝小程序
  • 百度开发者工具:调试百度小程序
  • 抖音开发者工具:调试字节跳动小程序
  • QQ开发者工具:调试QQ小程序

快速开始

1. 克隆项目

bash
git clone https://github.com/your-repo/ruoyi-plus-uniapp.git
cd plus-uniapp

2. 安装依赖

bash
# 使用 pnpm(推荐)
pnpm install

# 或使用 npm
npm install

3. 启动开发

H5 开发

bash
pnpm dev:h5

访问:http://localhost:100

微信小程序开发

bash
pnpm dev:mp-weixin

然后:

  1. 打开微信开发者工具
  2. 导入项目目录:dist/dev/mp-weixin
  3. 配置小程序 AppID

App 开发

bash
pnpm dev:app

然后:

  1. 打开 HBuilderX
  2. 导入项目目录:dist/dev/app
  3. 连接手机或模拟器运行

4. 生产构建

bash
# H5 构建
pnpm build:h5

# 微信小程序构建
pnpm build:mp-weixin

# App 构建
pnpm build:app

uni-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说明
viewdiv 标签
scroll-view滚动区域
swiper轮播组件
video视频播放
map地图组件
canvas画布

样式差异

  • H5:支持完整的 CSS3
  • 小程序:部分 CSS3 特性受限
  • 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

问题: 微信开发者工具无法打开项目

解决方案:

  1. 确保已运行 pnpm dev:mp-weixin
  2. 在微信开发者工具中导入 dist/dev/mp-weixin 目录
  3. 在开发者工具设置中启用"不校验合法域名"

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. 性能优化建议

小程序包体积优化:

  1. 启用分包加载
json
{
  "subPackages": [
    {
      "root": "pages-sub",
      "pages": [
        { "path": "detail/index" }
      ]
    }
  ]
}
  1. 按需引入组件
typescript
// 仅导入需要的组件
import { WdButton, WdIcon } from '@/wd'
  1. 使用 Tree Shaking
typescript
// vite.config.ts
export default defineConfig({
  build: {
    rollupOptions: {
      treeshake: true
    }
  }
})

渲染性能优化:

  1. 使用虚拟列表处理长列表
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>
  1. 避免不必要的重渲染
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

调试步骤:

  1. 打开微信开发者工具
  2. 导入 dist/dev/mp-weixin 目录
  3. 使用开发者工具的调试面板
  4. 查看 AppData 面板了解数据状态
  5. 使用远程调试功能真机调试

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

发布流程:

  1. 打开微信开发者工具
  2. 导入 dist/build/mp-weixin 目录
  3. 点击"上传"按钮
  4. 填写版本号和备注
  5. 在微信公众平台提交审核

3. App 打包

bash
# 生产构建
pnpm build:app

使用 HBuilderX 打包:

  1. 打开 HBuilderX
  2. 导入项目
  3. 发行 → 原生App-云打包
  4. 配置签名证书
  5. 等待打包完成

版本升级

升级 uni-app 版本

bash
# 使用官方升级工具
pnpm uvm

# 或手动升级
pnpm add @dcloudio/uni-app@latest

升级注意事项

  1. 备份项目:升级前备份代码和依赖锁文件
  2. 阅读更新日志:了解 Breaking Changes
  3. 测试功能:升级后在各平台测试核心功能
  4. 更新依赖:同步更新相关插件和依赖