From 7aa96ebb1962f312432bc06c215b5c6df7b7f0a5 Mon Sep 17 00:00:00 2001 From: MrWindlike Date: Thu, 23 Jun 2022 15:00:43 +0800 Subject: [PATCH] perf: improve the struct tree performance --- .../StructureTree/StructureTree.tsx | 42 ++++++++++++++++++- packages/shared/src/utils/function.ts | 17 ++++++++ 2 files changed, 57 insertions(+), 2 deletions(-) diff --git a/packages/editor/src/components/StructureTree/StructureTree.tsx b/packages/editor/src/components/StructureTree/StructureTree.tsx index 2ed56882..710e1e5c 100644 --- a/packages/editor/src/components/StructureTree/StructureTree.tsx +++ b/packages/editor/src/components/StructureTree/StructureTree.tsx @@ -6,7 +6,7 @@ import { DropComponentWrapper } from './DropComponentWrapper'; import { resolveApplicationComponents } from '../../utils/resolveApplicationComponents'; import ErrorBoundary from '../ErrorBoundary'; import { EditorServices } from '../../types'; -import { CORE_VERSION, CoreComponentName } from '@sunmao-ui/shared'; +import { CORE_VERSION, CoreTraitName, CoreComponentName, memo } from '@sunmao-ui/shared'; import { AutoComplete, AutoCompleteInput, @@ -15,6 +15,7 @@ import { type Item, } from '@choc-ui/chakra-autocomplete'; import { css } from '@emotion/css'; +import { isEqual } from 'lodash-es'; export type ChildrenMap = Map; type SlotsMap = Map; @@ -30,6 +31,43 @@ const AutoCompleteStyle = css` margin-top: 0; margin-bottom: 0.5rem; `; +const SLOT_TYPE = `${CORE_VERSION}/${CoreTraitName.Slot}`; + +const memoResolveApplicationComponents = memo( + resolveApplicationComponents, + function ([preRealComponents = []] = [], [realComponents]) { + // if add or remove the component, the struct tree should update + if (preRealComponents.length !== realComponents.length) { + return false; + } + + for (const i in realComponents) { + const preComponent = preRealComponents[i]; + const component = realComponents[i]; + + if (preComponent !== component) { + // there are two situations would cause the ids are different + // 1. the component id is changed + // 2. the order of components is changed. example: [a, b] -> [b, a] + if (preComponent.id !== component.id) { + return false; + } + + // should check the slot container whether is changed too because move a component to a slot may not change the order + const preSlotTrait = preComponent.traits.find(trait => trait.type === SLOT_TYPE); + const slotTrait = component.traits.find(trait => trait.type === SLOT_TYPE); + + if ( + !isEqual(preSlotTrait?.properties.container, slotTrait?.properties.container) + ) { + return false; + } + } + } + + return true; + } +); export const StructureTree: React.FC = props => { const [search, setSearch] = useState(''); @@ -69,7 +107,7 @@ export const StructureTree: React.FC = props => { const componentEles = useMemo(() => { const { topLevelComponents, childrenMap } = - resolveApplicationComponents(realComponents); + memoResolveApplicationComponents(realComponents); return topLevelComponents.map(c => ( ( + fn: (...params: P) => T, + compare: (preParams: P | [], newParams: P) => boolean +): (...params: P) => T { + let result: T | null = null; + let preParams: P | [] = []; + + return function (...params) { + if (result !== null && compare(preParams, params)) { + return result; + } else { + preParams = params; + return (result = fn(...params)); + } + }; +}