|
|
@@ -0,0 +1,193 @@
|
|
|
+# uni-app 页面加载提示对比分析
|
|
|
+
|
|
|
+## 概述
|
|
|
+本文档对比分析了 uni-app 项目中两种常见的页面加载提示实现方式:全局加载提示和骨架屏加载动画。通过对比 `my-patients.vue` 和 `message-detail.vue` 两个页面的具体实现,总结各自的特点、适用场景和优缺点。
|
|
|
+
|
|
|
+## 实现方式对比
|
|
|
+
|
|
|
+### 1. 全局加载提示(my-patients.vue)
|
|
|
+
|
|
|
+#### 实现原理
|
|
|
+- 使用 uni-app 提供的 `uni.showLoading()` 和 `uni.hideLoading()` API
|
|
|
+- 在数据请求开始时显示全局模态框,请求完成后隐藏
|
|
|
+
|
|
|
+#### 代码示例
|
|
|
+```typescript
|
|
|
+const fetchPatients = async () => {
|
|
|
+ uni.showLoading({ title: '加载中...' })
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 数据请求逻辑
|
|
|
+ const response = await listUserBindingsByBoundUser(...)
|
|
|
+ // 处理响应
|
|
|
+ } catch (error) {
|
|
|
+ // 错误处理
|
|
|
+ } finally {
|
|
|
+ uni.hideLoading()
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+#### 特点
|
|
|
+- **优点**:
|
|
|
+ - 实现简单,只需几行代码
|
|
|
+ - 用户体验一致,uni-app 原生支持
|
|
|
+ - 阻塞用户交互,防止重复操作
|
|
|
+- **缺点**:
|
|
|
+ - 全局模态框会遮挡整个页面
|
|
|
+ - 无法显示内容预览或进度信息
|
|
|
+ - 在小程序中可能有样式限制
|
|
|
+
|
|
|
+#### 适用场景
|
|
|
+- 数据加载时间较短(< 3秒)
|
|
|
+- 页面内容不需要预览
|
|
|
+- 希望阻止用户在加载期间进行其他操作
|
|
|
+
|
|
|
+### 2. 骨架屏加载动画(message-detail.vue)
|
|
|
+
|
|
|
+#### 实现原理
|
|
|
+- 使用 Vue 的条件渲染 `v-if="loading"`
|
|
|
+- 在模板中创建模拟真实内容的占位符结构
|
|
|
+- 通过 CSS 动画实现闪烁效果
|
|
|
+
|
|
|
+#### 代码示例
|
|
|
+```vue
|
|
|
+<template>
|
|
|
+ <!-- 骨架屏 -->
|
|
|
+ <view v-if="loading" class="skeleton-container">
|
|
|
+ <view class="skeleton-card" v-for="i in 3" :key="i">
|
|
|
+ <view class="skeleton-header">
|
|
|
+ <view class="skeleton-line skeleton-title"></view>
|
|
|
+ <view class="skeleton-line skeleton-small"></view>
|
|
|
+ </view>
|
|
|
+ <view class="skeleton-content">
|
|
|
+ <view class="skeleton-line skeleton-text"></view>
|
|
|
+ <view class="skeleton-line skeleton-text"></view>
|
|
|
+ <view class="skeleton-line skeleton-text skeleton-short"></view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <!-- 实际内容 -->
|
|
|
+ <view v-else class="message-list">
|
|
|
+ <!-- 真实消息列表 -->
|
|
|
+ </view>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup>
|
|
|
+const loading = ref(true)
|
|
|
+
|
|
|
+const fetchMessages = async () => {
|
|
|
+ loading.value = true
|
|
|
+ try {
|
|
|
+ // 数据请求逻辑
|
|
|
+ } finally {
|
|
|
+ loading.value = false
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|
|
|
+```
|
|
|
+
|
|
|
+#### CSS 样式示例
|
|
|
+```css
|
|
|
+.skeleton-line {
|
|
|
+ background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
|
|
+ background-size: 200% 100%;
|
|
|
+ animation: skeleton-loading 1.5s infinite;
|
|
|
+}
|
|
|
+
|
|
|
+@keyframes skeleton-loading {
|
|
|
+ 0% { background-position: 200% 0; }
|
|
|
+ 100% { background-position: -200% 0; }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+#### 特点
|
|
|
+- **优点**:
|
|
|
+ - 视觉体验更好,能预览页面布局
|
|
|
+ - 不阻塞用户交互,可以浏览其他内容
|
|
|
+ - 自定义程度高,可设计独特的加载动画
|
|
|
+ - 提升用户感知的加载速度
|
|
|
+- **缺点**:
|
|
|
+ - 实现复杂度较高,需要设计骨架结构
|
|
|
+ - 需要维护两套布局(骨架和真实内容)
|
|
|
+ - CSS 动画可能影响性能
|
|
|
+
|
|
|
+#### 适用场景
|
|
|
+- 数据加载时间较长(> 2秒)
|
|
|
+- 页面布局复杂,需要内容预览
|
|
|
+- 希望保持用户交互流畅性
|
|
|
+- 追求更好的视觉体验
|
|
|
+
|
|
|
+## 对比总结
|
|
|
+
|
|
|
+| 特性 | 全局加载提示 | 骨架屏加载动画 |
|
|
|
+|------|-------------|---------------|
|
|
|
+| 实现复杂度 | 低 | 中等 |
|
|
|
+| 用户体验 | 一般 | 优秀 |
|
|
|
+| 视觉效果 | 简单 | 丰富 |
|
|
|
+| 交互阻塞 | 是 | 否 |
|
|
|
+| 自定义程度 | 低 | 高 |
|
|
|
+| 性能影响 | 低 | 中等 |
|
|
|
+| 适用数据量 | 小数据 | 大数据/复杂页面 |
|
|
|
+
|
|
|
+## 选择建议
|
|
|
+
|
|
|
+1. **简单页面/快速加载**:推荐使用全局加载提示
|
|
|
+2. **复杂页面/慢速加载**:推荐使用骨架屏
|
|
|
+3. **混合使用**:可以结合两者,先显示骨架屏,再叠加全局提示
|
|
|
+
|
|
|
+## 最佳实践
|
|
|
+
|
|
|
+1. 根据页面复杂度选择合适的加载方式
|
|
|
+2. 设置合理的超时时间,避免无限加载
|
|
|
+3. 在错误情况下也要隐藏加载状态
|
|
|
+4. 考虑不同平台的兼容性
|
|
|
+5. 测试加载状态下的用户交互
|
|
|
+
|
|
|
+## 常见问题与解决方案
|
|
|
+
|
|
|
+### 骨架屏与实际内容同时显示问题
|
|
|
+
|
|
|
+#### 问题现象
|
|
|
+在使用骨架屏加载动画时,从其他页面(如编辑页面)返回时,骨架屏下方残留有之前的实际列表内容,导致加载状态与旧数据同时显示,影响用户体验。
|
|
|
+
|
|
|
+#### 问题原因
|
|
|
+模板中骨架屏使用 `v-if="loading"` 条件显示,但实际内容列表没有相应的条件隐藏。在数据重新加载期间,`loading` 为 true 时骨架屏显示,但旧的列表数据仍然可见,因为没有 `v-if="!loading"` 限制。
|
|
|
+
|
|
|
+#### 解决办法
|
|
|
+将实际内容区域包装在 `v-if="!loading"` 条件中,确保加载时只显示骨架屏,加载完成后显示实际内容。
|
|
|
+
|
|
|
+**错误示例:**
|
|
|
+```vue
|
|
|
+<view v-if="loading" class="skeleton-list">
|
|
|
+ <!-- 骨架屏 -->
|
|
|
+</view>
|
|
|
+<view class="news-card" v-for="item in list" :key="item.id">
|
|
|
+ <!-- 实际列表,无条件隐藏 -->
|
|
|
+</view>
|
|
|
+```
|
|
|
+
|
|
|
+**正确示例:**
|
|
|
+```vue
|
|
|
+<view v-if="loading" class="skeleton-list">
|
|
|
+ <!-- 骨架屏 -->
|
|
|
+</view>
|
|
|
+<view v-if="!loading">
|
|
|
+ <view class="news-card" v-for="item in list" :key="item.id">
|
|
|
+ <!-- 实际列表 -->
|
|
|
+ </view>
|
|
|
+ <!-- 其他内容如空状态、加载更多等 -->
|
|
|
+</view>
|
|
|
+```
|
|
|
+
|
|
|
+#### 经验教训
|
|
|
+- 骨架屏和实际内容应使用互斥的条件渲染,避免同时显示
|
|
|
+- 在页面重新加载(如 `onShow` 触发)时,确保旧数据被正确隐藏
|
|
|
+- 参考 `message-detail.vue` 的实现模式,确保加载状态管理的完整性
|
|
|
+
|
|
|
+## 相关文件
|
|
|
+- `src/pages/doctor/index/my-patients.vue` - 全局加载提示示例
|
|
|
+- `src/pages/public/message-detail.vue` - 骨架屏加载动画示例
|
|
|
+- `src/pages/doctor/manage/news.vue` - 骨架屏逻辑修复示例</content>
|
|
|
+<parameter name="filePath">d:\慢病APP\Dev\uniapp-ts\docs\uni-app 页面加载提示对比分析.md
|