perf(InstanceCanvas): 优化组件渲染性能

master
钟良源 1 week ago
parent 92dbdb0c79
commit 88b3f90138

@ -1,4 +1,4 @@
import React, { useState, useRef, useEffect } from 'react'; import React, { useState, useRef, useEffect, useMemo, useCallback, memo } from 'react';
import { ResizeBox, Tabs, Message, Spin, Table, TableColumnProps, Button } from '@arco-design/web-react'; import { ResizeBox, Tabs, Message, Spin, Table, TableColumnProps, Button } from '@arco-design/web-react';
import { IconCheckCircleFill, IconLoading, IconCloseCircleFill, IconLeft } from '@arco-design/web-react/icon'; import { IconCheckCircleFill, IconLoading, IconCloseCircleFill, IconLeft } from '@arco-design/web-react/icon';
import FlowEditor from '@/pages/flowEditor/index'; import FlowEditor from '@/pages/flowEditor/index';
@ -9,6 +9,21 @@ import styles from './index.module.less';
const TabPane = Tabs.TabPane; const TabPane = Tabs.TabPane;
// 使用 memo 包装 FlowEditor防止不必要的重新渲染
const MemoizedFlowEditor = memo(({ flowData, instanceId }: { flowData: any; instanceId: string }) => {
return (
<FlowEditor
key={instanceId}
initialData={flowData}
useDefault={true}
readOnly={true}
/>
);
}, (prevProps, nextProps) => {
// 自定义比较函数:只有当 instanceId 变化时才重新渲染
return prevProps.instanceId === nextProps.instanceId;
});
interface LogMessage { interface LogMessage {
id: number; id: number;
type: string; type: string;
@ -35,9 +50,10 @@ const InstanceCanvas: React.FC<InstanceCanvasProps> = ({ instanceData, title, on
const [flowData, setFlowData] = useState<any>(null); // 流程数据 const [flowData, setFlowData] = useState<any>(null); // 流程数据
const [loading, setLoading] = useState(false); // 加载状态 const [loading, setLoading] = useState(false); // 加载状态
const resizeBoxRef = useRef<HTMLDivElement>(null); const resizeBoxRef = useRef<HTMLDivElement>(null);
const flowDataRef = useRef<any>(null); // 使用 ref 来存储 flowData避免重复设置
// 获取实例定义数据 // 获取实例定义数据
const fetchInstanceDefinition = async () => { const fetchInstanceDefinition = useCallback(async () => {
if (!instanceData?.id) return; if (!instanceData?.id) return;
setLoading(true); setLoading(true);
@ -88,12 +104,18 @@ const InstanceCanvas: React.FC<InstanceCanvasProps> = ({ instanceData, title, on
return acc; return acc;
}, {} as any); }, {} as any);
setFlowData({ const newFlowData = {
components: convertedComponents, components: convertedComponents,
main: { main: {
components: convertedComponents components: convertedComponents
} }
}); };
// 只在数据真正变化时才更新
if (!flowDataRef.current) {
flowDataRef.current = newFlowData;
setFlowData(newFlowData);
}
} }
// 处理运行日志 // 处理运行日志
@ -139,12 +161,13 @@ const InstanceCanvas: React.FC<InstanceCanvasProps> = ({ instanceData, title, on
} finally { } finally {
setLoading(false); setLoading(false);
} }
}; }, [instanceData?.id]);
// 当 instanceData 变化时,重新获取数据 // 当 instanceData 变化时,重新获取数据
useEffect(() => { useEffect(() => {
flowDataRef.current = null; // 重置 ref
fetchInstanceDefinition(); fetchInstanceDefinition();
}, [instanceData?.id]); }, [instanceData?.id, fetchInstanceDefinition]);
// 处理 Tab 点击事件 // 处理 Tab 点击事件
const handleTabClick = (key: string) => { const handleTabClick = (key: string) => {
@ -165,7 +188,7 @@ const InstanceCanvas: React.FC<InstanceCanvasProps> = ({ instanceData, title, on
}, [logBarExpanded, logContainerHeight]); }, [logBarExpanded, logContainerHeight]);
// 处理 ResizeBox 手动调整大小事件 // 处理 ResizeBox 手动调整大小事件
const handleResize = (e: MouseEvent, size: { width: number; height: number }) => { const handleResize = useCallback((e: MouseEvent, size: { width: number; height: number }) => {
if (size.height <= 40) { if (size.height <= 40) {
setLogBarExpanded(false); setLogBarExpanded(false);
} }
@ -173,7 +196,7 @@ const InstanceCanvas: React.FC<InstanceCanvasProps> = ({ instanceData, title, on
setLogBarExpanded(true); setLogBarExpanded(true);
setLogContainerHeight(`${size.height}px`); setLogContainerHeight(`${size.height}px`);
} }
}; }, []);
// 渲染运行日志内容 // 渲染运行日志内容
const renderRuntimeLogs = () => { const renderRuntimeLogs = () => {
@ -317,7 +340,10 @@ const InstanceCanvas: React.FC<InstanceCanvasProps> = ({ instanceData, title, on
<span style={{ marginTop: '16px', color: 'var(--color-text-3)' }}>...</span> <span style={{ marginTop: '16px', color: 'var(--color-text-3)' }}>...</span>
</div> </div>
) : flowData ? ( ) : flowData ? (
<FlowEditor initialData={flowData} useDefault={true} readOnly={true} /> <MemoizedFlowEditor
flowData={flowData}
instanceId={instanceData?.id || 'instance-canvas'}
/>
) : ( ) : (
<div className={styles.emptyContainer}> <div className={styles.emptyContainer}>
<span></span> <span></span>

Loading…
Cancel
Save