UniApp 是 DCloud 推出的跨平台开发框架,使用 Vue.js 语法,可以一套代码编译到 iOS、Android、H5、以及各种小程序平台。本文将带你从零开始学习 UniApp。
什么是 UniApp?
UniApp 是一个使用 Vue.js 开发所有前端应用的框架,开发者编写一套代码,可发布到 iOS、Android、H5、以及各种小程序(微信/支付宝/百度/头条/QQ/快手/钉钉/淘宝)、快应用等多个平台。
核心优势
- 一套代码,多端运行:编写一次,发布到多个平台
- Vue.js 语法:学习成本低,上手快
- 丰富的组件库:内置大量 UI 组件
- 性能优秀:接近原生应用的性能
- 生态完善:插件市场丰富
环境搭建
1. 安装 HBuilderX
HBuilderX 是 DCloud 官方推荐的开发工具:
- 访问 HBuilderX 官网
- 下载并安装 HBuilderX
- 安装 uni-app 插件
2. 创建项目
在 HBuilderX 中:
- 文件 → 新建 → 项目
- 选择 uni-app
- 选择模板(推荐使用默认模板)
- 填写项目名称和路径
3. 使用 CLI 创建项目
# 全局安装 vue-cli
npm install -g @vue/cli
# 创建 uni-app 项目
vue create -p dcloudio/uni-preset-vue my-project
# 进入项目目录
cd my-project
# 运行到 H5
npm run dev:h5
# 运行到微信小程序
npm run dev:mp-weixin
项目结构
my-project/
├── pages/ # 页面目录
│ ├── index/
│ │ └── index.vue
│ └── about/
│ └── about.vue
├── components/ # 组件目录
├── static/ # 静态资源
├── App.vue # 应用入口
├── main.js # 入口文件
├── manifest.json # 应用配置
└── pages.json # 页面路由配置
基础语法
1. 页面结构
<template>
<view class="container">
<text>{{ message }}</text>
<button @click="handleClick">点击我</button>
</view>
</template>
<script>
export default {
data() {
return {
message: 'Hello UniApp!'
}
},
methods: {
handleClick() {
uni.showToast({
title: '点击成功',
icon: 'success'
})
}
}
}
</script>
<style>
.container {
padding: 20px;
}
</style>
2. 生命周期
<script>
export default {
onLoad(options) {
// 页面加载时触发
console.log('页面加载', options)
},
onShow() {
// 页面显示时触发
console.log('页面显示')
},
onReady() {
// 页面初次渲染完成
console.log('页面渲染完成')
},
onHide() {
// 页面隐藏时触发
console.log('页面隐藏')
},
onUnload() {
// 页面卸载时触发
console.log('页面卸载')
}
}
</script>
3. 路由导航
// 保留当前页面,跳转到应用内的某个页面
uni.navigateTo({
url: '/pages/detail/detail?id=123'
})
// 关闭当前页面,跳转到应用内的某个页面
uni.redirectTo({
url: '/pages/index/index'
})
// 跳转到 tabBar 页面
uni.switchTab({
url: '/pages/index/index'
})
// 返回上一页面
uni.navigateBack({
delta: 1 // 返回的页面数
})
常用组件
1. view 容器组件
<template>
<view class="container">
<view class="box">内容区域</view>
</view>
</template>
2. text 文本组件
<template>
<text>普通文本</text>
<text class="highlight">高亮文本</text>
</template>
3. image 图片组件
<template>
<image
src="/static/logo.png"
mode="aspectFit"
@error="handleError"
/>
</template>
4. button 按钮组件
<template>
<button type="primary" @click="handleClick">
主要按钮
</button>
<button type="default">默认按钮</button>
<button type="warn">警告按钮</button>
</template>
5. input 输入框
<template>
<input
v-model="inputValue"
placeholder="请输入内容"
@input="handleInput"
/>
</template>
<script>
export default {
data() {
return {
inputValue: ''
}
},
methods: {
handleInput(e) {
console.log('输入值:', e.detail.value)
}
}
}
</script>
条件渲染和列表渲染
条件渲染
<template>
<view>
<view v-if="show">显示内容</view>
<view v-else>隐藏内容</view>
<view v-show="visible">v-show 控制</view>
</view>
</template>
列表渲染
<template>
<view>
<view v-for="(item, index) in list" :key="index">
{{ item.name }}
</view>
</view>
</template>
<script>
export default {
data() {
return {
list: [
{ name: '项目1' },
{ name: '项目2' },
{ name: '项目3' }
]
}
}
}
</script>
API 使用
1. 网络请求
// 使用 uni.request
uni.request({
url: 'https://api.example.com/data',
method: 'GET',
data: {
id: 123
},
success: (res) => {
console.log('请求成功', res.data)
},
fail: (err) => {
console.error('请求失败', err)
}
})
// 封装请求方法
const request = (url, method = 'GET', data = {}) => {
return new Promise((resolve, reject) => {
uni.request({
url,
method,
data,
success: (res) => {
if (res.statusCode === 200) {
resolve(res.data)
} else {
reject(res)
}
},
fail: reject
})
})
}
// 使用
async function fetchData() {
try {
const data = await request('https://api.example.com/data')
console.log(data)
} catch (error) {
console.error(error)
}
}
2. 数据存储
// 同步存储
uni.setStorageSync('key', 'value')
const value = uni.getStorageSync('key')
// 异步存储
uni.setStorage({
key: 'key',
data: 'value',
success: () => {
console.log('存储成功')
}
})
uni.getStorage({
key: 'key',
success: (res) => {
console.log('获取成功', res.data)
}
})
3. 页面交互
// 显示提示
uni.showToast({
title: '操作成功',
icon: 'success',
duration: 2000
})
// 显示加载
uni.showLoading({
title: '加载中...'
})
// 隐藏加载
uni.hideLoading()
// 显示模态框
uni.showModal({
title: '提示',
content: '确定要删除吗?',
success: (res) => {
if (res.confirm) {
console.log('用户点击确定')
}
}
})
样式处理
1. 单位使用
<style>
.container {
width: 750rpx; /* rpx 是响应式单位,750rpx = 屏幕宽度 */
height: 100vh; /* 视口高度 */
padding: 20rpx;
}
</style>
2. 条件编译
<template>
<!-- #ifdef H5 -->
<view>H5 平台显示</view>
<!-- #endif -->
<!-- #ifdef MP-WEIXIN -->
<view>微信小程序显示</view>
<!-- #endif -->
<!-- #ifdef APP-PLUS -->
<view>App 平台显示</view>
<!-- #endif -->
</template>
<script>
// #ifdef H5
console.log('H5 平台')
// #endif
// #ifdef MP-WEIXIN
console.log('微信小程序平台')
// #endif
</script>
配置说明
pages.json
{
"pages": [
{
"path": "pages/index/index",
"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-current.png",
"text": "首页"
}
]
}
}
manifest.json
{
"name": "my-app",
"appid": "",
"description": "",
"versionName": "1.0.0",
"versionCode": "100",
"transformPx": false,
"app-plus": {
"usingComponents": true
},
"h5": {
"router": {
"mode": "hash"
}
},
"mp-weixin": {
"appid": "",
"setting": {
"urlCheck": false
}
}
}
实战示例
示例 1: 列表页面
<template>
<view class="container">
<view
v-for="(item, index) in list"
:key="index"
class="list-item"
@click="goToDetail(item)"
>
<image :src="item.image" class="item-image" />
<view class="item-content">
<text class="item-title">{{ item.title }}</text>
<text class="item-desc">{{ item.desc }}</text>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
list: []
}
},
onLoad() {
this.fetchList()
},
methods: {
async fetchList() {
try {
const res = await uni.request({
url: 'https://api.example.com/list'
})
this.list = res.data
} catch (error) {
uni.showToast({
title: '加载失败',
icon: 'none'
})
}
},
goToDetail(item) {
uni.navigateTo({
url: `/pages/detail/detail?id=${item.id}`
})
}
}
}
</script>
<style>
.container {
padding: 20rpx;
}
.list-item {
display: flex;
padding: 20rpx;
margin-bottom: 20rpx;
background: #fff;
border-radius: 10rpx;
}
.item-image {
width: 120rpx;
height: 120rpx;
border-radius: 10rpx;
}
.item-content {
flex: 1;
margin-left: 20rpx;
}
.item-title {
font-size: 32rpx;
font-weight: bold;
}
.item-desc {
font-size: 28rpx;
color: #999;
margin-top: 10rpx;
}
</style>
调试技巧
- H5 调试:使用浏览器开发者工具
- 小程序调试:使用对应平台的开发者工具
- App 调试:使用 HBuilderX 的真机运行功能
- 控制台输出:使用
console.log查看日志
常见问题
1. 样式不生效?
- 检查选择器是否正确
- 注意 rpx 单位的使用
- 检查是否有样式冲突
2. 页面跳转失败?
- 检查 pages.json 中是否配置了页面路径
- 检查 url 路径是否正确
- 注意 tabBar 页面需要使用
switchTab
3. 网络请求失败?
- 检查 manifest.json 中的网络权限配置
- 小程序平台需要配置合法域名
- 注意跨域问题
总结
UniApp 是一个强大的跨平台开发框架,通过本文的学习,你应该能够:
- 搭建 UniApp 开发环境
- 创建和配置项目
- 使用基础组件和 API
- 实现页面导航和数据交互
- 进行条件编译和样式处理
接下来可以深入学习:
- 组件库的使用(uView、ColorUI 等)
- 状态管理(Vuex)
- 插件开发
- 性能优化
开始你的 UniApp 跨平台开发之旅吧!
UniApp 让跨平台开发变得简单高效,一套代码多端运行,大大提升了开发效率。