203 lines
7.7 KiB
Markdown
203 lines
7.7 KiB
Markdown
# 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`
|