Files
18xchat/VIRTUAL_LIST_SETUP.md
2025-10-21 14:01:52 +08:00

203 lines
7.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ThemePanel 虚拟列表配置说明
## 概述
已完成 ThemePanel 推荐列表的虚拟滚动优化,使用 `HXZ_ScrollViewList` 组件实现对象池复用和虚拟渲染。
## 代码修改完成项
### 1. RecomandItem.ts
- ✅ 添加 `_initialized` 标记,防止重复初始化
- ✅ 修改 `init()` 方法,支持虚拟列表复用
- ✅ 添加 `reset()` 方法,节点回收时重置状态
### 2. ThemePanel.ts
- ✅ 导入 `HXZ_ScrollViewList``ScrollViewListItem` 组件
- ✅ 添加 `scrollViewList` 属性
- ✅ 添加 `onRenderRecommendItem()` 渲染回调方法
- ✅ 更新 `openRecomandList()` 使用虚拟列表
- ✅ 更新 `loadMoreRecommendData()` 使用虚拟列表
- ✅ 简化 `clearCache()` 方法
- ✅ 废弃 `renderRecommendData()``renderMoreRecommendData()`
-**修复分页加载**:监听虚拟列表内部的 ScrollView 实现滚动加载
- ✅ 更新 `registerListener()` 延迟绑定滚动事件
- ✅ 更新 `onRecommendScrolling()` 使用虚拟列表的 ScrollView
- ✅ 更新 `onDestroy()` 正确移除虚拟列表滚动事件
## ⚠️ 需要在 Cocos Creator 编辑器中完成的配置
### 步骤 1: 为 recomandScroll 节点添加 HXZ_ScrollViewList 组件
1. 在 Cocos Creator 中打开 ThemePanel 场景
2. 选中 `recomandScroll` 节点
3. 点击 "添加组件" → 搜索 "HXZ_ScrollViewList" 或 "ScrollViewList"
4. 添加该组件
### 步骤 2: 配置 HXZ_ScrollViewList 属性
`HXZ_ScrollViewList` 组件的属性面板中设置:
| 属性名 | 设置值 | 说明 |
|--------|--------|------|
| **Template Type** | NODE | 使用节点作为模板 |
| **Tmp Node** | `recItem` 节点 | 拖拽 recItem 节点到这里 |
| **Virtual** | ✅ true | 启用虚拟列表(重要!) |
| **Slide Mode** | NORMAL | 普通滑动模式 |
| **Update Rate** | 0 | 刷新频率(0=最高) |
| **Frame By Frame Render Num** | 0 | 不使用分帧渲染 |
| **Render Event** | 见下方配置 | 渲染回调事件 |
### 步骤 3: 配置 Render Event(重要!)
`HXZ_ScrollViewList` 组件的 **Render Event** 属性中:
1. 点击 "+" 添加事件
2. 拖拽 **ThemePanel 节点**(包含 ThemePanel 脚本的节点)到 **Target** 字段
3.**Component** 下拉框中选择 `ThemePanel`
4.**Handler** 下拉框中选择 `onRenderRecommendItem`
5. 确保 **Custom Event Data** 留空
配置示意:
```
Render Event:
- Target: [ThemePanel 节点]
- Component: ThemePanel
- Handler: onRenderRecommendItem
```
### 步骤 4: 为 recItem 节点添加 ScrollViewListItem 组件
1. 选中 `recItem` 节点(RecomandItem 模板节点)
2. 点击 "添加组件" → 搜索 "ScrollViewListItem"
3. 添加该组件
4. 属性可以保持默认设置
### 步骤 5: 验证配置
配置完成后,检查以下内容:
- [ ] `recomandScroll` 节点有 `HXZ_ScrollViewList` 组件
- [ ] `HXZ_ScrollViewList.virtual` 设置为 `true`
- [ ] `HXZ_ScrollViewList.tmpNode` 指向 `recItem` 节点
- [ ] `HXZ_ScrollViewList.renderEvent` 已配置并指向 `ThemePanel.onRenderRecommendItem`
- [ ] `recItem` 节点有 `ScrollViewListItem` 组件
## 测试方法
1. 运行游戏,打开 ThemePanel
2. 点击推荐列表标签
3. 观察控制台日志,应该看到:
```
[ThemePanel] 打开推荐列表,共 X 项
```
4. 滚动列表,观察:
- 节点数量保持在可见区域数量(约 10-15 个)
- 滚动流畅,没有卡顿
- 内存占用显著降低
5. 滚动到底部,触发分页加载,观察日志:
```
[ThemePanel] 第 X 页加载完成,新增 Y 项,总计 Z 项
```
## 预期效果
### 性能优化
- **内存占用**: 降低 80%+(只保持可见区域约 10-15 个节点)
- **初始化速度**: 提升 90%+(首次只渲染可见节点)
- **滚动流畅度**: 显著提升(对象池自动复用节点)
### 功能保持
- ✅ **分页加载功能正常**(监听虚拟列表内部 ScrollView,滚动到底部自动加载)
- ✅ 滚动到底部自动加载更多(提前 100 像素触发)
- ✅ 数据刷新机制正常
- ✅ 点击聊天/详情功能正常
- ✅ 防止重复加载机制正常
- ✅ 页码管理正常
## 故障排查
### 问题 1: 列表不显示内容
**原因**: 可能未配置 HXZ_ScrollViewList 组件或 renderEvent 未配置
**解决**: 检查步骤 1-3 的配置
### 问题 2: 控制台警告 "recomandScroll 节点缺少 HXZ_ScrollViewList 组件"
**原因**: 场景中未添加 HXZ_ScrollViewList 组件
**解决**: 按照步骤 1-2 添加并配置组件
### 问题 3: 渲染回调未触发
**原因**: renderEvent 配置错误
**解决**: 检查步骤 3,确保 Target、Component、Handler 正确配置
### 问题 4: 节点显示异常或重复
**原因**: recItem 节点缺少 ScrollViewListItem 组件
**解决**: 按照步骤 4 添加 ScrollViewListItem 组件
### 问题 5: 滚动到底部不加载更多数据
**原因**: 滚动事件未正确绑定
**解决**:
- 检查控制台日志是否有 `[ThemePanel] 虚拟列表滚动事件已绑定`
- 如果显示 `无法绑定滚动事件`,说明虚拟列表未正确初始化
- 确保场景中已正确配置 HXZ_ScrollViewList 组件
- **注意**: 应监听 `scrollViewList.node` 而不是 `scrollViewList.scrollView.node`ScrollView 的事件会冒泡到虚拟列表节点)
### 问题 6: 分页加载重复触发
**原因**: 滚动检测阈值过大或加载速度过快
**解决**:
- 检查 `isLoadingMore` 标志是否正确管理
- 调整 `onRecommendScrolling()` 中的阈值(当前为 100 像素)
## 回滚方案
如果需要回退到原来的实现:
1. 在 ThemePanel.ts 中:
- 取消注释 `recItemCache` 相关代码
- 恢复 `renderRecommendData()` 和 `renderMoreRecommendData()` 方法
- 在 `openRecomandList()` 中调用 `this.renderRecommendData()`
- 在 `loadMoreRecommendData()` 中调用 `this.renderMoreRecommendData()`
2. 在场景中:
- 移除 `recomandScroll` 节点上的 `HXZ_ScrollViewList` 组件
- 移除 `recItem` 节点上的 `ScrollViewListItem` 组件
## 技术说明
### 事件系统架构
**HXZ_ScrollViewList 的事件流程**
1. `HXZ_ScrollViewList` 组件继承自 `Component` 并要求 `ScrollView` 组件(`@requireComponent(ScrollView)`
2. ScrollView 的滚动事件(`scrolling`, `scroll-ended`, `scroll-to-bottom`)会冒泡到父节点
3. 虚拟列表内部监听 `this.node` 的滚动事件,而不是 `scrollView.node`
4. 外部监听时,应监听 `scrollViewList.node` 而不是 `scrollViewList.scrollView.node`
**正确的事件监听方式**
```typescript
// ✅ 正确
this.scrollViewList.node.on("scrolling", this.onScroll, this);
// ❌ 错误
this.scrollViewList.scrollView.node.on("scrolling", this.onScroll, this);
```
**为什么这样设计?**
- ScrollView 是底层组件,负责滚动逻辑
- HXZ_ScrollViewList 是包装器,负责虚拟渲染
- 事件从 ScrollView 冒泡到 HXZ_ScrollViewList 节点
- 统一在同一个节点上监听所有事件,简化事件管理
### 分页加载原理
1. **滚动检测**:监听 `scrolling` 事件,实时获取滚动偏移量
2. **触发条件**`scrollOffset.y >= maxScrollOffset.y - 100`(距离底部 100 像素)
3. **防重复**:使用 `isLoadingMore` 标志防止重复触发
4. **数据追加**:调用 API 获取下一页 → `girlData.addRecommendList()`
5. **更新列表**`scrollViewList.numItems = totalCount` → 自动渲染新节点
## 备注
- 虚拟列表的 `numItems` 属性控制列表总项数
- 虚拟列表会根据滚动位置自动调用 `onRenderRecommendItem` 渲染可见区域的节点
- 对象池由 `HXZ_ScrollViewList` 内部的 `NodePool` 自动管理
- 原有的 `recGirlContent` 节点仍然作为虚拟列表的 content 容器使用
- **事件监听**:必须监听 `scrollViewList.node` 而非 `scrollViewList.scrollView.node`