342 lines
8.1 KiB
Markdown
342 lines
8.1 KiB
Markdown
|
|
# 分销中心Loading优化说明 - v2(微信原生API)
|
|||
|
|
|
|||
|
|
## 一、优化背景
|
|||
|
|
|
|||
|
|
**原实现**:使用自定义loading组件(CSS动画 + WXML结构)
|
|||
|
|
|
|||
|
|
**问题**:
|
|||
|
|
- 代码冗余,需要维护额外的WXML和CSS
|
|||
|
|
- 样式可能与微信小程序原生风格不一致
|
|||
|
|
- 增加了页面复杂度
|
|||
|
|
|
|||
|
|
**优化方案**:使用微信小程序原生API `wx.showLoading()` 和 `wx.hideLoading()`
|
|||
|
|
|
|||
|
|
## 二、优化内容
|
|||
|
|
|
|||
|
|
### 1. 移除自定义Loading组件
|
|||
|
|
|
|||
|
|
#### WXML修改 (`miniprogram/pages/referral/referral.wxml`)
|
|||
|
|
|
|||
|
|
**删除:**
|
|||
|
|
```xml
|
|||
|
|
<!-- 删除自定义loading组件 -->
|
|||
|
|
<view class="loading-overlay" wx:if="{{isLoading}}">
|
|||
|
|
<view class="loading-content">
|
|||
|
|
<view class="loading-spinner"></view>
|
|||
|
|
<text class="loading-text">加载中...</text>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
|
|||
|
|
<!-- 删除content的动态class -->
|
|||
|
|
<view class="content {{isLoading ? 'content-loading' : ''}}">
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**改为:**
|
|||
|
|
```xml
|
|||
|
|
<!-- 使用微信原生loading,无需WXML代码 -->
|
|||
|
|
<view class="content">
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### JS修改 (`miniprogram/pages/referral/referral.js`)
|
|||
|
|
|
|||
|
|
**删除data中的isLoading:**
|
|||
|
|
```javascript
|
|||
|
|
data: {
|
|||
|
|
isLoading: false, // ❌ 删除
|
|||
|
|
// ...
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**使用微信原生API:**
|
|||
|
|
```javascript
|
|||
|
|
// 初始化数据
|
|||
|
|
async initData() {
|
|||
|
|
const { isLoggedIn, userInfo } = app.globalData
|
|||
|
|
if (isLoggedIn && userInfo) {
|
|||
|
|
// ✅ 显示微信原生loading
|
|||
|
|
wx.showLoading({
|
|||
|
|
title: '加载中...',
|
|||
|
|
mask: true // 防止触摸穿透
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
// ... 数据加载逻辑
|
|||
|
|
|
|||
|
|
this.setData({
|
|||
|
|
// ... 设置数据
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
// ✅ 隐藏loading
|
|||
|
|
wx.hideLoading()
|
|||
|
|
|
|||
|
|
} catch (e) {
|
|||
|
|
console.log('[Referral] ❌ API调用失败:', e)
|
|||
|
|
// ✅ 失败也要隐藏loading
|
|||
|
|
wx.hideLoading()
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### WXSS修改 (`miniprogram/pages/referral/referral.wxss`)
|
|||
|
|
|
|||
|
|
**删除:**
|
|||
|
|
```css
|
|||
|
|
/* ❌ 删除所有自定义loading样式 */
|
|||
|
|
.loading-overlay { ... }
|
|||
|
|
.loading-content { ... }
|
|||
|
|
.loading-spinner { ... }
|
|||
|
|
@keyframes spin { ... }
|
|||
|
|
.loading-text { ... }
|
|||
|
|
.content-loading { ... }
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 三、微信原生Loading API详解
|
|||
|
|
|
|||
|
|
### wx.showLoading(Object)
|
|||
|
|
|
|||
|
|
**参数说明:**
|
|||
|
|
```javascript
|
|||
|
|
wx.showLoading({
|
|||
|
|
title: '加载中...', // 提示的内容
|
|||
|
|
mask: true, // 是否显示透明蒙层,防止触摸穿透(建议true)
|
|||
|
|
success: function() {}, // 接口调用成功的回调函数(可选)
|
|||
|
|
fail: function() {}, // 接口调用失败的回调函数(可选)
|
|||
|
|
complete: function() {} // 接口调用结束的回调函数(可选)
|
|||
|
|
})
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**特点:**
|
|||
|
|
- ✅ 原生组件,性能优异
|
|||
|
|
- ✅ 自动居中显示
|
|||
|
|
- ✅ 与微信小程序风格统一
|
|||
|
|
- ✅ 自带菊花图(loading icon)
|
|||
|
|
- ✅ 支持透明蒙层,防止用户误触
|
|||
|
|
|
|||
|
|
### wx.hideLoading()
|
|||
|
|
|
|||
|
|
**用法:**
|
|||
|
|
```javascript
|
|||
|
|
wx.hideLoading() // 无需参数,直接调用
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**注意事项:**
|
|||
|
|
1. ⚠️ `wx.showLoading` 和 `wx.hideLoading` 必须配对使用
|
|||
|
|
2. ⚠️ 同一时间只能显示一个loading,多次调用 `wx.showLoading` 会覆盖
|
|||
|
|
3. ⚠️ 如果忘记调用 `wx.hideLoading`,用户会一直看到loading
|
|||
|
|
4. ✅ 建议在 `try-catch` 的 `finally` 或 `catch` 中也调用 `wx.hideLoading()`
|
|||
|
|
|
|||
|
|
### 与 wx.showToast 的区别
|
|||
|
|
|
|||
|
|
| 特性 | wx.showLoading | wx.showToast |
|
|||
|
|
|------|---------------|--------------|
|
|||
|
|
| 用途 | 数据加载中 | 操作结果反馈 |
|
|||
|
|
| 图标 | 菊花图(loading icon) | 成功/失败/警告图标 |
|
|||
|
|
| 自动关闭 | ❌ 需要手动 `wx.hideLoading()` | ✅ 自动关闭(默认1.5秒) |
|
|||
|
|
| 蒙层 | ✅ 支持mask参数 | ✅ 支持mask参数 |
|
|||
|
|
| 互斥 | 与 `wx.showToast` 互斥 | 与 `wx.showLoading` 互斥 |
|
|||
|
|
|
|||
|
|
## 四、优化前后对比
|
|||
|
|
|
|||
|
|
### 代码量对比
|
|||
|
|
|
|||
|
|
| 文件 | 优化前 | 优化后 | 减少 |
|
|||
|
|
|------|--------|--------|------|
|
|||
|
|
| WXML | +7行 | 0行 | -7行 |
|
|||
|
|
| JS | `isLoading` state + `this.setData()` | 2行API调用 | -3行 |
|
|||
|
|
| WXSS | +50行 | 0行 | -50行 |
|
|||
|
|
| **总计** | **+60行** | **2行** | **-58行** |
|
|||
|
|
|
|||
|
|
### 性能对比
|
|||
|
|
|
|||
|
|
| 指标 | 自定义Loading | 微信原生Loading |
|
|||
|
|
|------|---------------|----------------|
|
|||
|
|
| 渲染性能 | 需要WXML渲染 | 原生组件,更快 |
|
|||
|
|
| 内存占用 | 额外DOM节点 | 无额外DOM |
|
|||
|
|
| 样式一致性 | 需要手动调整 | 与微信风格统一 |
|
|||
|
|
| 维护成本 | 高 | 低 |
|
|||
|
|
|
|||
|
|
### 用户体验对比
|
|||
|
|
|
|||
|
|
**自定义Loading:**
|
|||
|
|
- 需要自己设计样式
|
|||
|
|
- 可能与微信小程序风格不一致
|
|||
|
|
- 动画性能依赖CSS实现
|
|||
|
|
|
|||
|
|
**微信原生Loading:**
|
|||
|
|
- ✅ 与微信小程序风格统一
|
|||
|
|
- ✅ 用户熟悉的交互体验
|
|||
|
|
- ✅ 性能更优
|
|||
|
|
|
|||
|
|
## 五、最佳实践
|
|||
|
|
|
|||
|
|
### 1. 基本用法
|
|||
|
|
|
|||
|
|
```javascript
|
|||
|
|
async loadData() {
|
|||
|
|
wx.showLoading({ title: '加载中...', mask: true })
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
const data = await fetchData()
|
|||
|
|
this.setData({ data })
|
|||
|
|
} catch (e) {
|
|||
|
|
wx.showToast({ title: '加载失败', icon: 'none' })
|
|||
|
|
} finally {
|
|||
|
|
wx.hideLoading() // ✅ 确保一定会关闭
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2. 多个异步操作
|
|||
|
|
|
|||
|
|
```javascript
|
|||
|
|
async loadMultipleData() {
|
|||
|
|
wx.showLoading({ title: '加载中...', mask: true })
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
// 并行请求
|
|||
|
|
const [data1, data2, data3] = await Promise.all([
|
|||
|
|
fetchData1(),
|
|||
|
|
fetchData2(),
|
|||
|
|
fetchData3()
|
|||
|
|
])
|
|||
|
|
|
|||
|
|
this.setData({ data1, data2, data3 })
|
|||
|
|
} catch (e) {
|
|||
|
|
wx.showToast({ title: '加载失败', icon: 'none' })
|
|||
|
|
} finally {
|
|||
|
|
wx.hideLoading()
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3. 动态提示文案
|
|||
|
|
|
|||
|
|
```javascript
|
|||
|
|
async syncData() {
|
|||
|
|
wx.showLoading({ title: '同步数据中...', mask: true })
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
await syncToServer()
|
|||
|
|
wx.hideLoading()
|
|||
|
|
wx.showToast({ title: '同步成功', icon: 'success' })
|
|||
|
|
} catch (e) {
|
|||
|
|
wx.hideLoading()
|
|||
|
|
wx.showToast({ title: '同步失败', icon: 'none' })
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 4. 防止重复调用
|
|||
|
|
|
|||
|
|
```javascript
|
|||
|
|
data: {
|
|||
|
|
isRequesting: false // 添加请求锁
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
async loadData() {
|
|||
|
|
if (this.data.isRequesting) return // ✅ 防止重复请求
|
|||
|
|
|
|||
|
|
this.setData({ isRequesting: true })
|
|||
|
|
wx.showLoading({ title: '加载中...', mask: true })
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
const data = await fetchData()
|
|||
|
|
this.setData({ data })
|
|||
|
|
} finally {
|
|||
|
|
wx.hideLoading()
|
|||
|
|
this.setData({ isRequesting: false })
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 六、常见问题
|
|||
|
|
|
|||
|
|
### Q1: Loading不关闭怎么办?
|
|||
|
|
|
|||
|
|
**原因:**
|
|||
|
|
- 忘记调用 `wx.hideLoading()`
|
|||
|
|
- 请求出错,没有在catch中关闭
|
|||
|
|
|
|||
|
|
**解决:**
|
|||
|
|
```javascript
|
|||
|
|
// ✅ 使用 finally 确保一定关闭
|
|||
|
|
try {
|
|||
|
|
// ...
|
|||
|
|
} finally {
|
|||
|
|
wx.hideLoading()
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Q2: Loading和Toast冲突?
|
|||
|
|
|
|||
|
|
**原因:**
|
|||
|
|
`wx.showLoading` 和 `wx.showToast` 互斥,同一时间只能显示一个。
|
|||
|
|
|
|||
|
|
**解决:**
|
|||
|
|
```javascript
|
|||
|
|
// ❌ 错误:loading没关闭就显示toast
|
|||
|
|
wx.showLoading({ title: '加载中...' })
|
|||
|
|
wx.showToast({ title: '操作成功' }) // 不会显示
|
|||
|
|
|
|||
|
|
// ✅ 正确:先关闭loading再显示toast
|
|||
|
|
wx.showLoading({ title: '加载中...' })
|
|||
|
|
await fetchData()
|
|||
|
|
wx.hideLoading()
|
|||
|
|
wx.showToast({ title: '操作成功' })
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Q3: 如何自定义Loading样式?
|
|||
|
|
|
|||
|
|
**答:**
|
|||
|
|
微信原生Loading不支持自定义样式。如果需要完全自定义样式,可以:
|
|||
|
|
1. 使用自定义组件(本次优化前的方案)
|
|||
|
|
2. 使用第三方UI库(如Vant Weapp)
|
|||
|
|
3. 考虑是否真的需要自定义(推荐使用原生)
|
|||
|
|
|
|||
|
|
### Q4: mask参数有什么用?
|
|||
|
|
|
|||
|
|
**答:**
|
|||
|
|
`mask: true` 会显示一个透明蒙层,防止用户在loading期间点击其他元素。
|
|||
|
|
|
|||
|
|
```javascript
|
|||
|
|
// ✅ 推荐:防止用户误触
|
|||
|
|
wx.showLoading({ title: '加载中...', mask: true })
|
|||
|
|
|
|||
|
|
// ⚠️ 不推荐:用户可能在加载时误触其他按钮
|
|||
|
|
wx.showLoading({ title: '加载中...', mask: false })
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 七、总结
|
|||
|
|
|
|||
|
|
### 优化成果
|
|||
|
|
|
|||
|
|
- ✅ 代码量减少 97%(60行 → 2行)
|
|||
|
|
- ✅ 无需维护自定义CSS和WXML
|
|||
|
|
- ✅ 性能更优(原生组件)
|
|||
|
|
- ✅ 用户体验更好(与微信风格统一)
|
|||
|
|
- ✅ 维护成本更低
|
|||
|
|
|
|||
|
|
### 建议
|
|||
|
|
|
|||
|
|
1. **优先使用微信原生API**
|
|||
|
|
- `wx.showLoading()` / `wx.hideLoading()`
|
|||
|
|
- `wx.showToast()`
|
|||
|
|
- `wx.showModal()`
|
|||
|
|
|
|||
|
|
2. **仅在必要时自定义**
|
|||
|
|
- 特殊设计需求
|
|||
|
|
- 品牌强相关的UI
|
|||
|
|
- 复杂交互场景
|
|||
|
|
|
|||
|
|
3. **遵循最佳实践**
|
|||
|
|
- 使用 `try-finally` 确保loading关闭
|
|||
|
|
- 设置 `mask: true` 防止误触
|
|||
|
|
- 避免loading和toast冲突
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
**优化时间**:2026-02-04
|
|||
|
|
**版本**:v2(微信原生API)
|
|||
|
|
**推荐指数**:⭐⭐⭐⭐⭐
|