作者:李移动开发 · 发布日期:2023年12月5日
什么是UniApp及其优势
UniApp是一个使用Vue.js开发所有前端应用的框架,开发者编写一套代码,可发布到iOS、Android、Web(响应式)、以及各种小程序(微信/支付宝/百度/头条/QQ/快手/钉钉/淘宝)、快应用等多个平台。
UniApp的主要优势:
- 跨平台能力:一套代码多端发布,大大减少开发成本
- 性能接近原生:通过weex强化,渲染性能大幅提升
- 丰富的插件市场:海量插件满足各种业务需求
- 学习成本低:基于Vue.js技术栈,前端开发者快速上手
- 良好的开发体验:HBuilderX提供强大的开发调试功能
开发环境搭建
开始UniApp开发前,需要配置相应的开发环境:
1. 安装HBuilderX
HBuilderX是官方推荐的IDE,提供了丰富的UniApp开发功能:
- 下载地址:https://www.dcloud.io/hbuilderx.html
- 选择App开发版,功能最完整
- 安装后安装相应的插件和编译器
2. 创建第一个UniApp项目
# 通过HBuilderX可视化创建:
# 1. 文件 → 新建 → 项目
# 2. 选择uni-app类型
# 3. 选择模板(推荐使用默认模板)
# 4. 输入项目名称并创建
# 或者使用命令行创建:
npm install -g @vue/cli
vue create -p dcloudio/uni-preset-vue my-project
cd my-project
npm run dev:%PLATFORM%
3. 安装必要的依赖
# 常用依赖
npm install uni-ui # 官方UI组件库
npm install sass # Sass预处理器
npm install axios # 网络请求库
# 微信小程序相关
npm install @dcloudio/uni-mp-weixin
项目结构解析
一个标准的UniApp项目结构如下:
my-uniapp-project/
├── pages/ # 页面目录
│ ├── index/
│ │ ├── index.vue # 首页
│ │ └── index.json # 页面配置
│ └── detail/
│ └── detail.vue # 详情页
├── components/ # 组件目录
├── static/ # 静态资源
├── uni_modules/ # uni模块
├── App.vue # 应用配置
├── main.js # 入口文件
├── manifest.json # 应用配置
├── pages.json # 页面配置
└── uni.scss # 全局样式
核心配置文件说明:
- pages.json:页面路由和窗口表现配置
- manifest.json:应用名称、图标、权限等配置
- App.vue:应用入口,可设置全局样式和脚本
电商应用核心功能实现
下面我们实现一个电商应用的主要功能模块:
1. 首页商品列表
<template>
<view class="container">
<!-- 搜索栏 -->
<view class="search-bar">
<uni-search-bar placeholder="搜索商品" @confirm="onSearch"></uni-search-bar>
</view>
<!-- 轮播图 -->
<swiper class="swiper" indicator-dots autoplay circular>
<swiper-item v-for="(item, index) in banners" :key="index">
<image :src="item.image" mode="aspectFill" class="swiper-image"></image>
</swiper-item>
</swiper>
<!-- 商品网格 -->
<view class="product-grid">
<view
class="product-item"
v-for="product in products"
:key="product.id"
@click="goToDetail(product.id)"
>
<image :src="product.thumbnail" mode="aspectFill"></image>
<text class="product-name">{{ product.name }}</text>
<text class="product-price">¥{{ product.price }}</text>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
banners: [
{ image: '/static/banner1.jpg', link: '' },
{ image: '/static/banner2.jpg', link: '' },
{ image: '/static/banner3.jpg', link: '' }
],
products: [],
loading: false
}
},
onLoad() {
this.loadProducts()
},
methods: {
async loadProducts() {
this.loading = true
try {
const res = await uni.request({
url: '/api/products',
method: 'GET'
})
this.products = res.data
} catch (error) {
uni.showToast({
title: '加载失败',
icon: 'none'
})
}
this.loading = false
},
onSearch(keyword) {
uni.navigateTo({
url: `/pages/search/search?keyword=${keyword}`
})
},
goToDetail(id) {
uni.navigateTo({
url: `/pages/detail/detail?id=${id}`
})
}
}
}
</script>
2. 商品详情页
<template>
<view class="detail-container">
<!-- 商品图片 -->
<swiper class="detail-swiper" indicator-dots>
<swiper-item v-for="(img, index) in product.images" :key="index">
<image :src="img" mode="aspectFit"></image>
</swiper-item>
</swiper>
<!-- 商品信息 -->
<view class="product-info">
<text class="product-title">{{ product.name }}</text>
<text class="product-price">¥{{ product.price }}</text>
<text class="product-desc">{{ product.description }}</text>
</view>
<!-- 规格选择 -->
<view class="spec-section">
<text class="section-title">规格选择</text>
<view class="spec-options">
<text
v-for="spec in product.specs"
:key="spec"
class="spec-option"
:class="{ active: selectedSpec === spec }"
@click="selectedSpec = spec"
>
{{ spec }}
</text>
</view>
</view>
<!-- 底部操作栏 -->
<view class="action-bar">
<button class="btn-cart" @click="addToCart">加入购物车</button>
<button class="btn-buy" @click="buyNow">立即购买</button>
</view>
</view>
</template>
<script>
export default {
data() {
return {
product: {},
selectedSpec: ''
}
},
onLoad(options) {
this.loadProductDetail(options.id)
},
methods: {
async loadProductDetail(id) {
const res = await uni.request({
url: `/api/products/${id}`,
method: 'GET'
})
this.product = res.data
this.selectedSpec = this.product.specs[0]
},
addToCart() {
uni.showToast({
title: '已加入购物车',
icon: 'success'
})
},
buyNow() {
uni.navigateTo({
url: `/pages/order/confirm?productId=${this.product.id}&spec=${this.selectedSpec}`
})
}
}
}
</script>
多平台适配技巧
UniApp虽然支持多平台,但不同平台仍有差异需要处理:
1. 条件编译
// #ifdef MP-WEIXIN
console.log('这是微信小程序环境')
// 微信小程序特有代码
// #endif
// #ifdef APP-PLUS
console.log('这是App环境')
// App特有代码
// #endif
// #ifdef H5
console.log('这是H5环境')
// H5特有代码
// #endif
2. 平台差异处理
// 导航栏高度适配
const getStatusBarHeight = () => {
// #ifdef APP-PLUS
return plus.navigator.getStatusbarHeight()
// #endif
// #ifdef MP-WEIXIN
const systemInfo = wx.getSystemInfoSync()
return systemInfo.statusBarHeight
// #endif
// #ifdef H5
return 0
// #endif
}
// 平台特定的API调用
const navigateTo = (url) => {
// #ifdef H5
window.location.href = url
// #endif
// #ifndef H5
uni.navigateTo({ url })
// #endif
}
打包与发布
完成开发后,需要将应用发布到各个平台:
1. 微信小程序发布
# 生成微信小程序代码
npm run build:mp-weixin
# 使用微信开发者工具
# 1. 导入项目:选择dist/dev/mp-weixin目录
# 2. 上传代码:工具 → 上传
# 3. 在微信公众平台提交审核
2. App打包发布
# 原生App云打包
# 1. HBuilderX → 发行 → 原生App-云打包
# 2. 配置证书和签名
# 3. 选择打包平台(iOS/Android)
# 4. 提交打包
# 或使用离线打包
# 参考官方离线打包文档:https://nativesupport.dcloud.net.cn/
3. H5部署
# 构建H5版本
npm run build:h5
# 部署到服务器
# 将dist/build/h5目录上传到Web服务器
# 配置路由重写(SPA需要)