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