UniApp 基础知识
一、UniApp 概述
1.1 什么是 UniApp
UniApp 是一个使用 Vue.js 开发所有前端应用的框架,开发者编写一套代码,可发布到 iOS、Android、H5、以及各种小程序(微信/支付宝/百度/头条/QQ/快手/钉钉/淘宝)等多个平台。
核心特点:
- 一套代码,多端运行
- 基于 Vue.js
- 丰富的组件和 API
- 条件编译,平台差异化
- 性能接近原生
1.2 支持的平台
| 平台 | 说明 |
|---|---|
| H5 | 浏览器 |
| 小程序 | 微信、支付宝、百度、头条、QQ、快手、钉钉、淘宝 |
| App | iOS、Android |
| 快应用 | 华为、小米等 |
1.3 技术架构
┌─────────────────────────────────┐
│ UniApp 框架层 │
├─────────────────────────────────┤
│ Vue.js + 条件编译 + 运行时 │
├─────────────────────────────────┤
│ 原生渲染层(各平台) │
└─────────────────────────────────┘
二、快速开始
2.1 安装 HBuilderX
- 下载 HBuilderX:www.dcloud.io/hbuilderx.h…
- 安装插件:uni-app 编译插件
- 创建项目:文件 → 新建 → 项目 → uni-app
2.2 使用 CLI 创建项目
# 安装 Vue CLI
npm install -g @vue/cli
# 创建项目
vue create -p dcloudio/uni-preset-vue my-project
# 进入项目
cd my-project
# 运行到 H5
npm run dev:h5
# 运行到微信小程序
npm run dev:mp-weixin
# 运行到 App
npm run dev:app-plus
2.3 项目结构
my-project/
├── pages/ # 页面目录
│ ├── index/
│ │ └── index.vue
│ └── about/
│ └── about.vue
├── components/ # 组件目录
├── static/ # 静态资源
├── uni_modules/ # uni-app 插件
├── App.vue # 应用入口
├── main.js # 入口文件
├── manifest.json # 应用配置
├── pages.json # 页面路由配置
└── uni.scss # 全局样式
三、页面配置
3.1 pages.json
{
"pages": [
{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "首页",
"enablePullDownRefresh": true,
"navigationBarBackgroundColor": "#007AFF",
"navigationBarTextStyle": "white"
}
},
{
"path": "pages/about/about",
"style": {
"navigationBarTitleText": "关于"
}
}
],
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "UniApp",
"navigationBarBackgroundColor": "#F8F8F8",
"backgroundColor": "#F8F8F8"
},
"tabBar": {
"color": "#7A7E83",
"selectedColor": "#3cc51f",
"borderStyle": "black",
"backgroundColor": "#ffffff",
"list": [
{
"pagePath": "pages/index/index",
"iconPath": "static/tab-home.png",
"selectedIconPath": "static/tab-home-active.png",
"text": "首页"
},
{
"pagePath": "pages/about/about",
"iconPath": "static/tab-about.png",
"selectedIconPath": "static/tab-about-active.png",
"text": "关于"
}
]
},
"condition": {
"current": 0,
"list": [
{
"name": "首页",
"path": "pages/index/index"
}
]
}
}
3.2 manifest.json
{
"name": "my-app",
"appid": "__UNI__XXXXX",
"description": "应用描述",
"versionName": "1.0.0",
"versionCode": "100",
"transformPx": false,
"app-plus": {
"usingComponents": true,
"nvueStyleCompiler": "uni-app",
"compilerVersion": 3,
"splashscreen": {
"alwaysShowBeforeRender": true,
"waiting": true,
"autoclose": true,
"delay": 0
}
},
"mp-weixin": {
"appid": "wxXXXXXXXX",
"setting": {
"urlCheck": false
},
"usingComponents": true
},
"h5": {
"router": {
"mode": "hash",
"base": "/"
}
}
}
四、页面和组件
4.1 页面结构
<template>
<view class="container">
<text>{{ message }}</text>
<button @click="handleClick">点击</button>
</view>
</template>
<script>
export default {
data() {
return {
message: 'Hello UniApp'
}
},
onLoad(options) {
// 页面加载
console.log('页面加载', options)
},
onShow() {
// 页面显示
},
onReady() {
// 页面初次渲染完成
},
methods: {
handleClick() {
this.message = '点击了按钮'
}
}
}
</script>
<style>
.container {
padding: 20px;
}
</style>
4.2 页面生命周期
export default {
onLoad(options) {
// 页面加载,接收参数
},
onShow() {
// 页面显示/切入前台
},
onReady() {
// 页面初次渲染完成
},
onHide() {
// 页面隐藏/切入后台
},
onUnload() {
// 页面卸载
},
onPullDownRefresh() {
// 下拉刷新
setTimeout(() => {
uni.stopPullDownRefresh()
}, 1000)
},
onReachBottom() {
// 上拉触底
},
onPageScroll(e) {
// 页面滚动
console.log(e.scrollTop)
}
}
4.3 组件使用
<template>
<view>
<!-- 使用组件 -->
<my-component :data="userData" @update="handleUpdate" />
</view>
</template>
<script>
import MyComponent from '@/components/MyComponent.vue'
export default {
components: {
MyComponent
},
data() {
return {
userData: {
name: 'zhangsan',
age: 25
}
}
},
methods: {
handleUpdate(data) {
console.log('更新', data)
}
}
}
</script>
五、路由和导航
5.1 页面跳转
// 保留当前页面,跳转到应用内的某个页面
uni.navigateTo({
url: '/pages/detail/detail?id=1&name=test',
success: (res) => {
console.log('成功', res)
},
fail: (err) => {
console.log('失败', err)
}
})
// 关闭当前页面,跳转到应用内的某个页面
uni.redirectTo({
url: '/pages/detail/detail'
})
// 跳转到 tabBar 页面
uni.switchTab({
url: '/pages/index/index'
})
// 关闭所有页面,打开到应用内的某个页面
uni.reLaunch({
url: '/pages/index/index'
})
// 返回上一页面
uni.navigateBack({
delta: 1 // 返回的页面数
})
5.2 页面传参
// 跳转时传参
uni.navigateTo({
url: '/pages/detail/detail?id=1&name=test'
})
// 接收参数
export default {
onLoad(options) {
console.log(options.id) // 1
console.log(options.name) // 'test'
}
}
5.3 页面通信
// 方式1:通过 getCurrentPages 获取页面栈
const pages = getCurrentPages()
const prevPage = pages[pages.length - 2]
prevPage.setData({
message: '来自详情页'
})
// 方式2:使用全局事件总线
// main.js
Vue.prototype.$eventBus = new Vue()
// 页面A
this.$eventBus.$emit('update', data)
// 页面B
this.$eventBus.$on('update', (data) => {
console.log(data)
})
六、常用组件
6.1 基础组件
<template>
<!-- 视图容器 -->
<view class="container">
<!-- 文本 -->
<text>文本内容</text>
<text selectable>可选文本</text>
<!-- 图片 -->
<image src="/static/logo.png" mode="aspectFit" />
<!-- 按钮 -->
<button type="primary" @click="handleClick">按钮</button>
<button type="default" size="mini">小按钮</button>
<!-- 输入框 -->
<input v-model="inputValue" placeholder="请输入" />
<!-- 文本域 -->
<textarea v-model="textareaValue" placeholder="多行文本" />
<!-- 滚动视图 -->
<scroll-view scroll-y="true" @scrolltolower="loadMore">
<view v-for="item in list" :key="item.id">
{{ item.name }}
</view>
</scroll-view>
</view>
</template>
6.2 表单组件
<template>
<form @submit="handleSubmit">
<!-- 单选框 -->
<radio-group @change="radioChange">
<radio value="1" :checked="radioValue === '1'">选项1</radio>
<radio value="2" :checked="radioValue === '2'">选项2</radio>
</radio-group>
<!-- 复选框 -->
<checkbox-group @change="checkboxChange">
<checkbox value="A" :checked="true">选项A</checkbox>
<checkbox value="B">选项B</checkbox>
</checkbox-group>
<!-- 开关 -->
<switch :checked="switchValue" @change="switchChange" />
<!-- 滑块 -->
<slider :value="sliderValue" @change="sliderChange" />
<!-- 选择器 -->
<picker mode="selector" :range="pickerRange" @change="pickerChange">
<view>当前选择:{{ pickerValue }}</view>
</picker>
<!-- 日期选择器 -->
<picker mode="date" @change="dateChange">
<view>选择日期:{{ dateValue }}</view>
</picker>
<button form-type="submit">提交</button>
</form>
</template>
<script>
export default {
data() {
return {
radioValue: '1',
switchValue: false,
sliderValue: 50,
pickerRange: ['选项1', '选项2', '选项3'],
pickerValue: '选项1',
dateValue: ''
}
},
methods: {
radioChange(e) {
this.radioValue = e.detail.value
},
checkboxChange(e) {
console.log(e.detail.value)
},
switchChange(e) {
this.switchValue = e.detail.value
},
sliderChange(e) {
this.sliderValue = e.detail.value
},
pickerChange(e) {
this.pickerValue = this.pickerRange[e.detail.value]
},
dateChange(e) {
this.dateValue = e.detail.value
},
handleSubmit(e) {
console.log('表单提交', e.detail.value)
}
}
}
</script>
6.3 媒体组件
<template>
<!-- 视频 -->
<video
src="https://example.com/video.mp4"
controls
@play="onPlay"
@pause="onPause"
/>
<!-- 音频 -->
<audio
src="https://example.com/audio.mp3"
controls
/>
<!-- 相机 -->
<camera
device-position="back"
@error="cameraError"
/>
</template>
七、API 使用
7.1 网络请求
// uni.request
uni.request({
url: 'https://api.example.com/data',
method: 'GET',
data: {
id: 1,
name: 'test'
},
header: {
'Content-Type': 'application/json',
'Authorization': 'Bearer token'
},
success: (res) => {
console.log('成功', res.data)
},
fail: (err) => {
console.log('失败', err)
}
})
// 封装请求
const request = (options) => {
return new Promise((resolve, reject) => {
uni.request({
...options,
success: (res) => {
if (res.statusCode === 200) {
resolve(res.data)
} else {
reject(res)
}
},
fail: reject
})
})
}
// 使用
const data = await request({
url: '/api/data',
method: 'GET'
})
7.2 数据存储
// 同步存储
uni.setStorageSync('key', 'value')
const value = uni.getStorageSync('key')
uni.removeStorageSync('key')
uni.clearStorageSync()
// 异步存储
uni.setStorage({
key: 'key',
data: 'value',
success: () => {
console.log('存储成功')
}
})
uni.getStorage({
key: 'key',
success: (res) => {
console.log('获取成功', res.data)
}
})
uni.removeStorage({
key: 'key',
success: () => {
console.log('删除成功')
}
})
7.3 界面交互
// 提示框
uni.showToast({
title: '操作成功',
icon: 'success',
duration: 2000
})
// 加载提示
uni.showLoading({
title: '加载中...'
})
uni.hideLoading()
// 模态对话框
uni.showModal({
title: '提示',
content: '确定要删除吗?',
success: (res) => {
if (res.confirm) {
console.log('确定')
} else if (res.cancel) {
console.log('取消')
}
}
})
// 操作菜单
uni.showActionSheet({
itemList: ['选项1', '选项2', '选项3'],
success: (res) => {
console.log('选择了', res.tapIndex)
}
})
7.4 设备信息
// 获取系统信息
uni.getSystemInfo({
success: (res) => {
console.log('屏幕宽度', res.windowWidth)
console.log('屏幕高度', res.windowHeight)
console.log('状态栏高度', res.statusBarHeight)
console.log('平台', res.platform)
}
})
// 获取网络类型
uni.getNetworkType({
success: (res) => {
console.log('网络类型', res.networkType)
}
})
// 监听网络状态
uni.onNetworkStatusChange((res) => {
console.log('网络状态', res.isConnected)
})
7.5 位置和地图
// 获取当前位置
uni.getLocation({
type: 'gcj02',
success: (res) => {
console.log('纬度', res.latitude)
console.log('经度', res.longitude)
}
})
// 打开地图
uni.openLocation({
latitude: 39.9,
longitude: 116.4,
name: '位置名称',
address: '详细地址'
})
// 选择位置
uni.chooseLocation({
success: (res) => {
console.log('位置', res)
}
})
八、条件编译
8.1 代码条件编译
// #ifdef H5
console.log('只在 H5 平台执行')
// #endif
// #ifdef MP-WEIXIN
console.log('只在微信小程序执行')
// #endif
// #ifdef APP-PLUS
console.log('只在 App 执行')
// #endif
// #ifndef H5
console.log('除了 H5 平台都执行')
// #endif
// #ifdef H5 || MP-WEIXIN
console.log('H5 或微信小程序执行')
// #endif
8.2 样式条件编译
/* #ifdef H5 */
.container {
background: blue;
}
/* #endif */
/* #ifdef MP-WEIXIN */
.container {
background: green;
}
/* #endif */
8.3 页面条件编译
{
"pages": [
// #ifdef H5
{
"path": "pages/h5/h5",
"style": {}
},
// #endif
// #ifdef MP-WEIXIN
{
"path": "pages/weixin/weixin",
"style": {}
},
// #endif
]
}
8.4 静态资源条件编译
static/
├── logo.png # 所有平台
├── logo-h5.png # 仅 H5
├── logo-mp-weixin.png # 仅微信小程序
└── logo-app.png # 仅 App
九、样式和布局
9.1 尺寸单位
<template>
<!-- rpx:响应式像素,750rpx = 屏幕宽度 -->
<view style="width: 750rpx; height: 100rpx;"></view>
<!-- px:像素 -->
<view style="width: 375px; height: 50px;"></view>
<!-- 百分比 -->
<view style="width: 50%;"></view>
</template>
9.2 Flex 布局
<template>
<view class="container">
<view class="item">1</view>
<view class="item">2</view>
<view class="item">3</view>
</view>
</template>
<style>
.container {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
}
.item {
flex: 1;
}
</style>
9.3 全局样式
// uni.scss
$uni-color-primary: #007AFF;
$uni-color-success: #4CD964;
$uni-color-warning: #F0AD4E;
$uni-color-error: #DD524D;
// 使用
.text-primary {
color: $uni-color-primary;
}
十、插件和扩展
10.1 uni-ui 组件库
# 安装
npm install @dcloudio/uni-ui
# 使用
<template>
<uni-icons type="contact" size="30" />
<uni-badge text="99" type="error" />
<uni-card title="标题" note="备注">
<text>内容</text>
</uni-card>
</template>
10.2 第三方插件
# 安装插件
npm install vuex-persistedstate
# 使用
import createPersistedState from 'vuex-persistedstate'
const store = new Vuex.Store({
plugins: [createPersistedState()]
})
十一、性能优化
11.1 图片优化
<template>
<!-- 使用 webp 格式 -->
<image src="/static/image.webp" />
<!-- 懒加载 -->
<image
src="/static/image.jpg"
lazy-load
mode="aspectFit"
/>
<!-- 使用网络图片时压缩 -->
<image
:src="imageUrl"
mode="aspectFit"
@error="handleImageError"
/>
</template>
11.2 列表优化
<template>
<!-- 使用 key -->
<view v-for="item in list" :key="item.id">
{{ item.name }}
</view>
<!-- 虚拟列表(大数据) -->
<recycle-list
:list="largeList"
template-key="type"
/>
</template>
11.3 代码分包
{
"subPackages": [
{
"root": "pages/sub1",
"pages": [
{
"path": "index/index",
"style": {}
}
]
}
],
"preloadRule": {
"pages/index/index": {
"network": "all",
"packages": ["pages/sub1"]
}
}
}
十二、常见问题
12.1 平台差异
// 处理平台差异
// #ifdef H5
// H5 特定代码
// #endif
// #ifdef MP-WEIXIN
// 微信小程序特定代码
// #endif
// #ifdef APP-PLUS
// App 特定代码
// #endif
12.2 样式兼容
/* 使用条件编译 */
/* #ifdef H5 */
.container {
/* H5 样式 */
}
/* #endif */
/* #ifdef MP-WEIXIN */
.container {
/* 小程序样式 */
}
/* #endif */
12.3 调试技巧
// 开发环境调试
// #ifdef H5
console.log('H5 调试')
// #endif
// #ifdef MP-WEIXIN
console.log('小程序调试')
// #endif
// 使用 uni.showToast 调试
uni.showToast({
title: JSON.stringify(data),
icon: 'none',
duration: 3000
})
十三、发布和打包
13.1 H5 发布
# 构建 H5
npm run build:h5
# 部署到服务器
# 将 dist/build/h5 目录上传到服务器
13.2 小程序发布
# 构建微信小程序
npm run build:mp-weixin
# 使用微信开发者工具打开 dist/build/mp-weixin
# 上传代码,提交审核
13.3 App 打包
# 构建 App
npm run build:app-plus
# 使用 HBuilderX
# 1. 发行 → 原生 App-云打包
# 2. 或使用本地打包
十四、最佳实践
14.1 项目结构
project/
├── pages/ # 页面
├── components/ # 组件
├── static/ # 静态资源
├── utils/ # 工具函数
├── api/ # API 接口
├── store/ # 状态管理
├── common/ # 公共文件
└── uni_modules/ # uni-app 插件
14.2 代码规范
// ✅ 使用 async/await
async function fetchData() {
try {
const res = await uni.request({
url: '/api/data'
})
return res.data
} catch (error) {
console.error(error)
}
}
// ✅ 统一错误处理
const handleError = (error) => {
uni.showToast({
title: error.message || '操作失败',
icon: 'none'
})
}
14.3 性能优化
// ✅ 使用防抖节流
import { debounce, throttle } from '@/utils/index'
// 防抖
const handleSearch = debounce((keyword) => {
// 搜索逻辑
}, 500)
// 节流
const handleScroll = throttle(() => {
// 滚动逻辑
}, 200)
十五、推荐资源
官方文档:
- UniApp 官网:uniapp.dcloud.net.cn/
- UniApp API:uniapp.dcloud.net.cn/api/
- UniApp 组件:uniapp.dcloud.net.cn/component/
学习资源:
- 《UniApp 跨平台开发实战》
- UniApp 社区:ask.dcloud.net.cn/
- UniApp 插件市场:ext.dcloud.net.cn/
十六、总结
UniApp 核心要点:
一套代码 + 多端运行 + 条件编译 + 丰富组件 = 高效跨平台开发
核心心法:
UniApp 让跨平台开发变得简单。 掌握条件编译是处理平台差异的关键。
📝 文档信息
- 作者: 阿鑫
- 更新日期: 2026.1