1. 项目背景与核心功能解析
"黑马优购"是一个基于uni-app框架开发的跨平台电商类微信小程序项目。作为实战教学案例,它完整覆盖了从商品展示、购物车管理到订单支付的全流程电商功能模块。这个项目特别适合有一定前端基础,想要快速掌握微信小程序开发核心技能的开发者。
我在实际开发中发现,uni-app框架最大的优势在于"一次编写,多端发布"。通过Vue.js语法开发,可以同时生成微信小程序、H5页面和安卓App。在黑马优购项目中,我们主要关注微信小程序端的实现,但代码结构设计时已经预留了多端适配的扩展性。
提示:虽然uni-app支持多端,但微信小程序有自己特殊的API和限制条件,开发时需要注意平台差异处理。
项目核心功能模块包括:
- 首页商品瀑布流展示
- 分类页面的多级商品筛选
- 商品详情页的SKU选择器
- 购物车的本地缓存管理
- 微信支付接入与订单状态跟踪
- 用户授权登录与个人信息管理
2. 技术架构与开发环境搭建
2.1 uni-app框架选型考量
选择uni-app而非原生小程序开发主要基于三个考虑:
- 开发效率:Vue语法比小程序原生语法更友好,组件化开发体验更好
- 团队协作:现有团队成员熟悉Vue技术栈,学习曲线平缓
- 成本控制:一套代码可发布到多个平台,降低后期维护成本
实际开发中,我们使用的是HBuilderX 3.4.7版本,搭配微信开发者工具进行调试。这个组合在开发体验上相当流畅,特别是HBuilderX对uni-app的深度支持,提供了很多便捷的代码提示和快速编译功能。
2.2 项目目录结构设计
经过多次迭代,我们最终采用的目录结构如下:
code复制├── common // 公共资源
│ ├── fonts // 字体图标
│ └── scss // 全局样式
├── components // 公共组件
│ ├── cart-control // 购物车按钮
│ └── sku-selector // SKU选择器
├── pages // 页面目录
│ ├── cart // 购物车
│ └── product // 商品详情
├── static // 静态资源
├── store // Vuex状态管理
└── utils // 工具函数
这种结构的特点是业务逻辑与UI组件分离,便于团队协作和后期维护。特别是将商品SKU选择器这类复杂组件独立封装,可以在多个页面复用。
3. 核心功能实现细节
3.1 商品列表性能优化
商品列表页面临的主要挑战是大量图片加载导致的性能问题。我们采用了以下优化方案:
- 图片懒加载:使用uni-app的
<image>组件配合lazy-load属性
html复制<image
:src="item.image"
mode="aspectFill"
lazy-load
@load="imageLoaded"
/>
- 分页加载策略:结合触底加载和虚拟列表
javascript复制onReachBottom() {
if(this.loading || !this.hasMore) return
this.pageNum++
this.getGoodsList()
}
- 图片CDN加速:所有商品图片经过压缩后上传到腾讯云COS,并开启WebP自动转换
实测下来,这些优化使列表滚动流畅度提升60%以上,特别是在低端安卓设备上效果明显。
3.2 购物车本地缓存方案
购物车功能需要解决两个核心问题:
- 未登录用户的临时购物车存储
- 已登录用户与服务端的数据同步
我们的实现方案是:
javascript复制// 获取购物车数据
getCart() {
if(this.isLogin) {
// 从服务端获取
return api.getCart()
} else {
// 从本地存储获取
return uni.getStorageSync('tempCart') || []
}
}
// 更新购物车
updateCart(items) {
if(this.isLogin) {
await api.updateCart(items)
} else {
uni.setStorageSync('tempCart', items)
}
}
注意:本地存储有大小限制(微信小程序约10MB),对于可能大量数据的场景需要做清理策略。
3.3 微信支付接入实战
支付功能是电商项目的核心,也是新手最容易踩坑的地方。我们的支付流程如下:
- 前端调用统一下单接口
javascript复制const res = await uni.request({
url: '/api/createOrder',
method: 'POST',
data: orderInfo
})
- 服务端返回支付参数后调用微信支付
javascript复制uni.requestPayment({
timeStamp: res.timeStamp,
nonceStr: res.nonceStr,
package: res.package,
signType: 'MD5',
paySign: res.paySign,
success: () => {
// 支付成功处理
},
fail: (err) => {
console.error('支付失败', err)
}
})
- 支付状态轮询检查
javascript复制// 设置定时器检查订单状态
const timer = setInterval(async () => {
const status = await checkOrderStatus(orderNo)
if(status === 'paid') {
clearInterval(timer)
// 跳转到支付成功页
}
}, 3000)
在实际项目中,我们遇到了华为鸿蒙系统下获取微信登录code失败的问题,最终通过增加错误重试机制解决。
4. 多端适配与打包发布
4.1 微信小程序特殊处理
虽然uni-app支持多端,但微信小程序有许多特殊限制需要处理:
- 导航栏高度适配:
javascript复制// 获取系统信息
const systemInfo = uni.getSystemInfoSync()
// 计算导航栏高度
this.navBarHeight = systemInfo.statusBarHeight + 44
- 分包加载配置:
json复制{
"subPackages": [
{
"root": "pages/sub1",
"pages": ["index/detail"]
}
]
}
- 域名白名单配置:所有请求域名都需要在微信公众平台配置合法域名
4.2 安卓App打包要点
通过uni-app云打包生成安卓APK时需要注意:
- 配置manifest.json中的App模块权限
- 处理Android特有的后退键行为
- 适配全面屏和异形屏显示
- 处理应用启动图与微信小程序的差异
打包命令示例:
bash复制# 发行安卓App
uni-build --platform android --prod
5. 开发中的典型问题与解决方案
5.1 网络请求封装与异常处理
我们对uni.request进行了二次封装,主要解决以下问题:
- 自动处理token过期刷新
- 统一错误码处理
- 请求取消功能
- 加载状态管理
核心实现代码:
javascript复制const request = (options) => {
// 合并配置
const config = {
baseURL: 'https://api.example.com',
...options
}
// 请求拦截
if (store.state.token) {
config.header = {
'Authorization': `Bearer ${store.state.token}`,
...config.header
}
}
return new Promise((resolve, reject) => {
uni.request({
...config,
success: (res) => {
if (res.statusCode === 401) {
// token过期处理
return refreshToken().then(() => request(options))
}
resolve(res.data)
},
fail: (err) => {
uni.showToast({
title: '网络错误',
icon: 'none'
})
reject(err)
}
})
})
}
5.2 样式适配问题汇总
- 1px边框问题:使用transform缩放实现
scss复制.border-1px {
position: relative;
&::after {
content: "";
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 1px;
background: #ddd;
transform: scaleY(0.5);
transform-origin: 0 0;
}
}
- 安全区域适配:处理iPhone X等设备的底部安全区域
css复制.safe-area-inset-bottom {
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
}
- 字体图标使用:推荐使用iconfont.cn生成字体文件
css复制@font-face {
font-family: 'iconfont';
src: url('/static/fonts/iconfont.ttf') format('truetype');
}
.icon {
font-family: 'iconfont';
}
6. 项目优化与扩展方向
6.1 性能优化实践
- 首屏加载优化:
- 使用分包加载
- 关键资源预加载
- 骨架屏占位
- 数据缓存策略:
- 接口数据本地缓存
- 图片内存缓存
- 列表项复用
- 渲染性能优化:
- 避免频繁setData
- 使用纯数据字段
- 长列表虚拟滚动
6.2 可扩展架构设计
为了使项目更容易维护和扩展,我们采用了以下架构设计:
- 状态管理:使用Vuex进行全局状态管理,模块化设计store
- 插件机制:封装常用功能为uni-app插件,如支付插件、分享插件
- 配置中心:所有环境变量和全局配置集中管理
- 错误监控:集成Sentry进行错误收集和分析
6.3 后续迭代计划
基于当前版本,我们规划了以下迭代方向:
- 增加直播带货功能
- 实现会员积分体系
- 接入更多支付方式
- 优化搜索和推荐算法
- 增强数据分析能力
在实际开发中,我发现uni-app的downloadFile在H5模式下确实存在无法获取临时文件路径的限制,这是框架层面的已知问题。对于需要兼容多端的文件下载功能,建议使用条件编译针对不同平台做差异化处理。
