87 lines
3.1 KiB
Markdown
87 lines
3.1 KiB
Markdown
# 素材库渲染性能经验
|
||
|
||
更新日期:2026-04-27
|
||
|
||
## 背景
|
||
|
||
部分用户打开素材库后,在素材卡片上移动鼠标会感到整个页面抖动;素材库弹窗标题偶尔消失。
|
||
|
||
这类问题不要只按“素材太多”处理。素材库本身已使用虚拟滚动,更常见的瓶颈来自高频 hover 下的弹层、阴影、透明模糊和窗口实例冲突。
|
||
|
||
## 根因
|
||
|
||
### 1. 高频 hover 不能批量创建弹层
|
||
|
||
素材卡片里每个名称、徽章、按钮都包 `Tooltip` 时,鼠标快速扫过网格会持续触发:
|
||
|
||
- 弹层创建和销毁
|
||
- 浮层定位计算
|
||
- portal 层级更新
|
||
- React 状态和浏览器重绘
|
||
|
||
在大量图片缩略图上,这些成本会叠加成明显抖动。
|
||
|
||
经验:
|
||
|
||
- 卡片列表中的非关键提示优先用原生 `title` 或静态文案。
|
||
- `Tooltip` 适合低密度工具栏,不适合高密度素材网格的每个子元素。
|
||
- 不可见的 overlay 也要注意鼠标命中,必要时加 `pointer-events: none`。
|
||
|
||
### 2. hover 样式要避免扩大绘制范围
|
||
|
||
素材卡片 hover 时如果同时使用大阴影、透明背景、`backdrop-filter` 和图片内容,浏览器需要频繁重新合成图层。
|
||
|
||
经验:
|
||
|
||
- 高密度列表 hover 优先保留轻量 `border-color`、背景色或图标显隐。
|
||
- 谨慎在列表项内使用 `backdrop-filter`。
|
||
- 卡片容器可加 `contain: layout paint`,把布局和绘制影响限制在卡片内部。
|
||
|
||
### 3. 固定 WinBox id 会制造偶发标题和层级问题
|
||
|
||
素材库有多个入口,部分页面可能同时挂载多个 `MediaLibraryModal`。如果组件内部固定传 `id="media-library"`,会导致:
|
||
|
||
- DOM id 重复
|
||
- WinBox 实例状态互相覆盖
|
||
- 窗口管理器注册/注销错配
|
||
- 标题栏和 z-index 出现偶发异常
|
||
|
||
经验:
|
||
|
||
- 可复用弹窗组件不要在内部写死窗口 id。
|
||
- 需要稳定 id 时,由调用方按业务场景传入唯一值。
|
||
- 没有强需求时,让窗口封装生成内部唯一 id。
|
||
|
||
## 推荐规则
|
||
|
||
1. 素材网格内的 hover 交互要按“高频路径”设计。
|
||
|
||
- 少建弹层。
|
||
- 少用模糊和大阴影。
|
||
- 少触发跨层级定位。
|
||
|
||
2. 列表项视觉反馈不能引发布局变化。
|
||
|
||
- 边框要配合 `box-sizing: border-box`。
|
||
- hover 不改变 item 尺寸。
|
||
- overlay 不参与鼠标命中。
|
||
|
||
3. 虚拟滚动只解决“渲染数量”,不解决“单项 hover 成本”。
|
||
|
||
- 可见区域仍可能有几十个媒体卡片。
|
||
- 单项效果越重,鼠标移动时越容易卡。
|
||
|
||
4. WinBox 类弹窗要避免实例身份冲突。
|
||
|
||
- 弹窗 id 是实例身份,不是功能名称。
|
||
- 多入口、多实例场景必须唯一。
|
||
- 标题图标优先用封装提供的 `icon` 插槽,不要用空的自定义标题内容挤占标题布局。
|
||
|
||
## 修复检查清单
|
||
|
||
- 鼠标扫过素材网格时,卡片只做轻量视觉变化。
|
||
- 素材名称、同步角标、缓存角标不再批量触发自定义 Tooltip。
|
||
- 卡片 hover 不改变布局尺寸,不影响相邻项。
|
||
- 弹窗组件没有固定复用同一个 WinBox id。
|
||
- 标题栏标题显式保持可见,图标和标题各走自己的插槽。
|