fix: optimize ArtifactListImpl

This commit is contained in:
tao.chen
2026-08-20 20:29:22 +08:00
parent 05c2157c4a
commit 3dc049f46e
3 changed files with 45 additions and 8 deletions
@@ -1,8 +1,13 @@
import { memo } from "react";
import { type ScheduleArtifact } from "../../services/api";
import Icon from "../../components/common/Icon";
import { shortHash } from "./utils";
export function ArtifactList({
// 包裹 memo 让父级 SchedulePage 在画布交互(setSelectedNodeId /
// setSelectedEdgeId / linkSourceId 等)重渲染时,artifact 卡片不会跟着
// 重建/重绑拖拽事件 —— 减少拖动过程中的事件重绑与列表抖动。
function ArtifactListImpl({
artifacts,
keyword,
onDrop,
@@ -77,3 +82,5 @@ export function ArtifactList({
</section>
);
}
export const ArtifactList = memo(ArtifactListImpl);
@@ -3,6 +3,7 @@ import {
type FormEvent,
memo,
type MouseEvent as ReactMouseEvent,
useCallback,
useEffect,
useMemo,
useRef,
@@ -307,6 +308,35 @@ export default function SchedulePage({
: artifacts;
}, [artifacts, artifactKeyword]);
// 稳定传给 ArtifactList 的 3 个回调,让 memo 真正生效 —— 否则父级
// (SchedulePage) 任何 store 字段变化都会让卡片列表重新绑定拖拽事件,
// 在拖动/快速 hover 时放大体感卡顿。
const handleArtifactDrop = useCallback(
(artifact: ScheduleArtifact, x: number, y: number) => {
useSchedulesStore.getState().addArtifactAt(artifact, x, y);
},
[],
);
const handleArtifactDoubleClick = useCallback(
(artifact: ScheduleArtifact) => {
useSchedulesStore.getState().addArtifactAt(
artifact,
90 + (schedule?.nodes.length ?? 0) * 245,
130,
);
},
[schedule],
);
const handleArtifactContextMenu = useCallback(
(event: ReactMouseEvent, artifact: ScheduleArtifact) => {
openScheduleContextMenu(
event as ReactMouseEvent<HTMLElement | SVGElement>,
{ kind: "artifact", artifact },
);
},
[],
);
return (
<section className="schedule-page">
<header className="schedule-toolbar">
@@ -364,9 +394,9 @@ export default function SchedulePage({
<ArtifactList
artifacts={filteredArtifacts}
keyword={artifactKeyword}
onDrop={(artifact, x, y) => void useSchedulesStore.getState().addArtifactAt(artifact, x, y)}
onDoubleClick={(artifact) => void useSchedulesStore.getState().addArtifactAt(artifact, 90 + (schedule?.nodes.length ?? 0) * 245, 130)}
onContextMenu={(event, artifact) => openScheduleContextMenu(event as ReactMouseEvent<HTMLElement | SVGElement>, { kind: "artifact", artifact })}
onDrop={handleArtifactDrop}
onDoubleClick={handleArtifactDoubleClick}
onContextMenu={handleArtifactContextMenu}
onKeywordChange={setArtifactKeyword}
/>
</aside>
+4 -4
View File
@@ -294,10 +294,10 @@
background: #fff;
cursor: grab;
user-select: none;
transition:
transform .15s ease,
box-shadow .15s ease,
border-color .15s ease;
/* hover 效果(border / box-shadow / transform)全部走合成层友好的属性,
但禁止 transition:box-shadow 是 paint 操作,在 20+ 张卡片上快速
划过鼠标会触发频繁重绘,导致悬浮卡顿;拖动时也会让 drag image 变重、
视觉上"粘"在半动画上。直接瞬变,干净利落。 */
}
.artifact-card:hover {