免费资源下载
一套代码同时发布到微信小程序、支付宝小程序、H5、App的完整开发指南
项目概述:现代化电商应用架构设计
核心功能模块
- 商品展示与分类系统
- 购物车与订单管理
- 用户认证与权限控制
- 支付集成(多平台适配)
- 实时消息推送
技术栈选型
- UniApp 3.0 + Vue 3 + TypeScript
- Pinia状态管理
- UniCloud云开发
- uView UI组件库
- Vite构建工具
一、环境配置与项目初始化
1.1 创建TypeScript支持的UniApp项目
# 使用Vue3 + TypeScript模板创建项目
vue create -p dcloudio/uni-preset-vue#vite-ts my-mall
# 安装必要依赖
npm install pinia @pinia/npm-detection
npm install uview-ui
npm install @uni-helper/uni-app-types --save-dev
# 配置tsconfig.json
{
"compilerOptions": {
"types": ["@dcloudio/types", "@uni-helper/uni-app-types"]
}
}
1.2 项目目录结构优化
src/ ├── api/ # 接口管理 ├── components/ # 公共组件 ├── composables/ # Vue组合式函数 ├── pages/ # 页面文件 ├── static/ # 静态资源 ├── store/ # Pinia状态管理 ├── types/ # TypeScript类型定义 ├── utils/ # 工具函数 └── uni.scss # 全局样式变量
二、核心架构设计与实现
2.1 基于Pinia的全局状态管理
// store/user.ts - 用户状态管理
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import type { UserInfo } from '@/types/user'
export const useUserStore = defineStore('user', () => {
const userInfo = ref(null)
const token = ref('')
const cartCount = ref(0)
// 计算属性
const isLogin = computed(() => !!token.value)
// Actions
const login = async (credentials: LoginParams) => {
const res = await uni.request({
url: '/api/auth/login',
method: 'POST',
data: credentials
})
token.value = res.data.token
userInfo.value = res.data.userInfo
uni.setStorageSync('token', token.value)
}
const updateCartCount = (count: number) => {
cartCount.value = count
// 同步到tabBar徽章
if (count > 0) {
uni.setTabBarBadge({
index: 2,
text: count.toString()
})
} else {
uni.removeTabBarBadge({ index: 2 })
}
}
return { userInfo, token, cartCount, isLogin, login, updateCartCount }
})
2.2 多平台适配的请求封装
// utils/request.ts - 统一请求拦截器
import { useUserStore } from '@/store/user'
const BASE_URL = process.env.VITE_API_BASE_URL
interface RequestOptions {
url: string
method?: 'GET' | 'POST' | 'PUT' | 'DELETE'
data?: any
header?: Record
loading?: boolean
}
export const request = async (options: RequestOptions): Promise => {
const userStore = useUserStore()
// 显示加载提示
if (options.loading !== false) {
uni.showLoading({ title: '加载中...', mask: true })
}
try {
const header = {
'Content-Type': 'application/json',
'Authorization': `Bearer ${userStore.token}`,
...options.header
}
const res = await uni.request({
url: `${BASE_URL}${options.url}`,
method: options.method || 'GET',
data: options.data,
header
})
// 处理不同平台的响应结构
#ifdef MP-WEIXIN
const data = res.data as ApiResponse
#endif
#ifdef H5
const data = res.data.data as T
#endif
if (res.statusCode !== 200) {
throw new Error(data.message || '请求失败')
}
return data
} catch (error) {
// 统一错误处理
uni.showToast({
title: error.message || '网络错误',
icon: 'none'
})
throw error
} finally {
uni.hideLoading()
}
}
三、关键功能模块实现
3.1 商品瀑布流列表
// components/ProductWaterfall.vue
<template>
<view class="waterfall-container">
<view v-for="(column, index) in columns"
:key="index"
class="waterfall-column">
<ProductCard
v-for="product in column"
:key="product.id"
:product="product"
@click="handleProductClick(product)" />
</view>
</view>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import type { Product } from '@/types/product'
const props = defineProps<{
products: Product[]
}>()
// 计算瀑布流列数据
const columns = computed(() => {
const cols: Product[][] = [[], []]
props.products.forEach((product, index) => {
cols[index % 2].push(product)
})
return cols
})
</script>
3.2 多平台支付集成
// utils/payment.ts
export const unifiedPayment = async (orderId: string) => {
// 获取支付参数
const paymentParams = await request({
url: `/api/orders/${orderId}/payment`,
method: 'POST'
})
// 多平台支付适配
#ifdef MP-WEIXIN
return await uni.requestPayment({
provider: 'wxpay',
...paymentParams
})
#endif
#ifdef MP-ALIPAY
return await uni.requestPayment({
provider: 'alipay',
...paymentParams
})
#endif
#ifdef H5 || APP-PLUS
// H5和App使用其他支付方式
window.location.href = paymentParams.payUrl
#endif
}
四、性能优化与最佳实践
4.1 图片懒加载与优化
实现方案:
- 使用uni.lazyLoad组件
- 图片预加载机制
- WebP格式自动降级
- CDN图片压缩
代码示例:
// 图片懒加载组件 <image :src="thumbnail" :lazy-load="true" :webp="true" @load="handleImageLoad" @error="handleImageError" mode="aspectFill"> <loading v-if="!loaded" /> </image>
4.2 分包加载策略
// pages.json 分包配置
{
"pages": [
{ "path": "pages/index/index", "style": { ... } }
],
"subPackages": [
{
"root": "pagesA",
"pages": [
{ "path": "product/detail", "style": { ... } },
{ "path": "product/list", "style": { ... } }
]
},
{
"root": "pagesB",
"pages": [
{ "path": "user/order", "style": { ... } },
{ "path": "user/address", "style": { ... } }
]
}
],
"preloadRule": {
"pages/index/index": {
"network": "all",
"packages": ["pagesA"]
}
}
}
五、多端发布与部署
微信小程序
# 生产环境构建 npm run build:mp-weixin # 使用CI/CD自动上传 微信开发者工具 CLI
H5部署
# 构建H5版本
npm run build:h5
# 部署到Nginx
location / {
try_files $uri $uri/ /index.html;
gzip on;
}
App打包
# 生成App资源 npm run build:app-plus # 使用HBuilderX # 原生插件集成 # 云打包服务
六、常见问题与解决方案
Q1: 如何解决不同平台样式差异?
使用条件编译和平台特有样式文件:
/* 平台特定样式 */
#ifdef MP-WEIXIN
.button { padding: 12px 24px; }
#endif
#ifdef H5
.button { padding: 10px 20px; }
#endif
/* 使用scss变量统一管理 */
$platform-padding: 12px;
#ifdef H5
$platform-padding: 10px;
#endif
Q2: 如何优化首屏加载速度?
- 使用骨架屏组件
- 合理配置分包预加载
- 启用gzip压缩
- 使用uni.onLaunch异步初始化
- 关键资源预加载

