修改布局,修复BUG
Some checks failed
CI / Test (ubuntu-latest) (push) Has been cancelled
CI / Test (windows-latest) (push) Has been cancelled
CI / Lint (ubuntu-latest) (push) Has been cancelled
CI / Lint (windows-latest) (push) Has been cancelled
CI / Check (ubuntu-latest) (push) Has been cancelled
CI / Check (windows-latest) (push) Has been cancelled
CI / CI OK (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
Deploy Website on push / Deploy Push Playground Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Docs Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Antd Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Element Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Naive Ftp (push) Has been cancelled
Deploy Website on push / Rerun on failure (push) Has been cancelled
Release Drafter / update_release_draft (push) Has been cancelled
Some checks failed
CI / Test (ubuntu-latest) (push) Has been cancelled
CI / Test (windows-latest) (push) Has been cancelled
CI / Lint (ubuntu-latest) (push) Has been cancelled
CI / Lint (windows-latest) (push) Has been cancelled
CI / Check (ubuntu-latest) (push) Has been cancelled
CI / Check (windows-latest) (push) Has been cancelled
CI / CI OK (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
Deploy Website on push / Deploy Push Playground Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Docs Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Antd Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Element Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Naive Ftp (push) Has been cancelled
Deploy Website on push / Rerun on failure (push) Has been cancelled
Release Drafter / update_release_draft (push) Has been cancelled
This commit is contained in:
142
doc/座位布局性能优化说明.md
Normal file
142
doc/座位布局性能优化说明.md
Normal file
@@ -0,0 +1,142 @@
|
||||
# 座位布局性能优化说明
|
||||
|
||||
## 问题描述
|
||||
|
||||
当座位布局节点数量很大时(例如 50x50 = 2500 个单元格),会出现明显的卡顿现象。主要原因是:
|
||||
|
||||
1. **大量 DOM 节点**:双重循环渲染所有单元格,创建大量 DOM 元素
|
||||
2. **重复计算**:每次渲染时,`getCellClass`、`getCellText`、`shouldRenderCell` 等函数都会被调用,且内部包含循环遍历
|
||||
3. **查找性能**:使用 `Array.find()` 查找单元格,时间复杂度为 O(n)
|
||||
4. **事件处理**:鼠标移动事件触发频繁,没有有效节流
|
||||
|
||||
## 优化方案
|
||||
|
||||
### 1. 使用 Map 缓存单元格查找
|
||||
|
||||
**优化前:**
|
||||
```typescript
|
||||
const getCell = (col: number, row: number) => {
|
||||
return cells.value.find((c) => c.col === col && c.row === row);
|
||||
};
|
||||
```
|
||||
|
||||
**优化后:**
|
||||
```typescript
|
||||
// 单元格查找缓存 Map: key = "col,row", value = cell
|
||||
const cellMapCache = ref<Map<string, ClassroomApi.ClassroomLayoutCell>>(new Map());
|
||||
|
||||
const getCell = (col: number, row: number) => {
|
||||
const key = `${col},${row}`;
|
||||
return cellMapCache.value.get(key);
|
||||
};
|
||||
```
|
||||
|
||||
**效果:** 查找时间复杂度从 O(n) 降低到 O(1)
|
||||
|
||||
### 2. 缓存合并单元格映射关系
|
||||
|
||||
**优化前:**
|
||||
```typescript
|
||||
// 每次都要遍历所有单元格检查是否被合并
|
||||
for (const otherCell of cells.value) {
|
||||
// ... 检查逻辑
|
||||
}
|
||||
```
|
||||
|
||||
**优化后:**
|
||||
```typescript
|
||||
// 合并单元格主单元格映射: key = "col,row" (被合并的单元格), value = "col,row" (主单元格)
|
||||
const mergeMasterMapCache = ref<Map<string, string>>(new Map());
|
||||
|
||||
// 使用缓存检查
|
||||
const key = `${col},${row}`;
|
||||
if (mergeMasterMapCache.value.has(key)) {
|
||||
return 'cell cell-merged';
|
||||
}
|
||||
```
|
||||
|
||||
**效果:** 避免了每次渲染时的 O(n²) 循环嵌套
|
||||
|
||||
### 3. 使用 shallowRef 优化响应式性能
|
||||
|
||||
**优化前:**
|
||||
```typescript
|
||||
const cells = ref<ClassroomApi.ClassroomLayoutCell[]>([]);
|
||||
```
|
||||
|
||||
**优化后:**
|
||||
```typescript
|
||||
const cells = shallowRef<ClassroomApi.ClassroomLayoutCell[]>([]);
|
||||
```
|
||||
|
||||
**效果:** 减少深度响应式监听,提升性能
|
||||
|
||||
### 4. 使用 requestAnimationFrame 优化鼠标移动事件
|
||||
|
||||
**优化前:**
|
||||
```typescript
|
||||
mouseEnterTimer = window.setTimeout(() => {
|
||||
// 填充逻辑
|
||||
}, 16);
|
||||
```
|
||||
|
||||
**优化后:**
|
||||
```typescript
|
||||
rafId = requestAnimationFrame(() => {
|
||||
// 填充逻辑
|
||||
});
|
||||
```
|
||||
|
||||
**效果:** 与浏览器渲染周期同步,更流畅
|
||||
|
||||
### 5. 使用 v-memo 指令缓存单元格渲染
|
||||
|
||||
**优化后:**
|
||||
```vue
|
||||
<div
|
||||
v-if="shouldRenderCell(col - 1, row - 1)"
|
||||
v-memo="[getCell(col - 1, row - 1)?.type, getCell(col - 1, row - 1)?.status, ...]"
|
||||
:class="getCellClass(col - 1, row - 1)"
|
||||
...
|
||||
>
|
||||
```
|
||||
|
||||
**效果:** 只有当依赖项变化时才重新渲染,减少不必要的 DOM 更新
|
||||
|
||||
### 6. 统一更新缓存机制
|
||||
|
||||
在所有修改单元格的操作后,统一调用 `updateCellMapCache()` 更新缓存:
|
||||
|
||||
- `initLayout()` - 初始化布局
|
||||
- `loadLayout()` - 加载布局
|
||||
- `addColumnLeft/Right()` - 添加列
|
||||
- `addRowTop/Bottom()` - 添加行
|
||||
- `mergeCells()` - 合并单元格
|
||||
- `unmergeCell()` - 取消合并
|
||||
- `handleUndo()` - 撤销操作
|
||||
- `handleCellMouseUp()` - 鼠标释放
|
||||
|
||||
## 性能提升
|
||||
|
||||
经过优化后,预期性能提升:
|
||||
|
||||
1. **单元格查找**:从 O(n) 降低到 O(1),查找速度提升 100-1000 倍(取决于单元格数量)
|
||||
2. **合并检查**:从 O(n²) 降低到 O(1),检查速度提升 10000 倍以上
|
||||
3. **渲染性能**:使用 v-memo 后,只有变化的单元格才会重新渲染
|
||||
4. **鼠标交互**:使用 requestAnimationFrame 后,交互更流畅,帧率更稳定
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. **缓存一致性**:所有修改单元格的操作都必须调用 `updateCellMapCache()` 保持缓存同步
|
||||
2. **内存占用**:Map 缓存会占用额外内存,但对于性能提升是值得的
|
||||
3. **兼容性**:`v-memo` 是 Vue 3.2+ 的特性,确保项目使用 Vue 3.2 或更高版本
|
||||
|
||||
## 后续优化建议
|
||||
|
||||
如果性能仍然不够理想,可以考虑:
|
||||
|
||||
1. **虚拟滚动**:只渲染可见区域的单元格(对 Grid 布局实现较复杂)
|
||||
2. **Canvas 渲染**:使用 Canvas 替代 DOM 渲染(需要重写交互逻辑)
|
||||
3. **Web Worker**:将复杂计算移到 Web Worker 中
|
||||
4. **分块渲染**:将大布局分成多个块,按需加载
|
||||
|
||||
Reference in New Issue
Block a user