mirror of
https://github.com/smartxworks/sunmao-ui.git
synced 2024-11-21 03:15:49 +08:00
memomize slotElements to avoid extra re-mount
This commit is contained in:
parent
3781cecf1f
commit
cc41138c8e
@ -14,7 +14,14 @@ export const ImplWrapper = React.memo<ImplWrapperProps>(
|
||||
|
||||
if (prevChildren && nextChildren) {
|
||||
isEqual = shallowCompareArray(prevChildren, nextChildren);
|
||||
} else if (prevChildren === nextChildren) {
|
||||
isEqual = true;
|
||||
}
|
||||
return isEqual && prevComponent === nextComponent;
|
||||
return (
|
||||
isEqual &&
|
||||
prevComponent === nextComponent &&
|
||||
// TODO: keep ImplWrapper memorized and get slot props from store
|
||||
prevProps.slotProps === nextProps.slotProps
|
||||
);
|
||||
}
|
||||
);
|
||||
|
@ -4,13 +4,13 @@ import { RuntimeTraitSchema } from '@sunmao-ui/core';
|
||||
import { watch } from '../../../utils/watchReactivity';
|
||||
import { ImplWrapperProps, TraitResult } from '../../../types';
|
||||
import { useRuntimeFunctions } from './hooks/useRuntimeFunctions';
|
||||
import { useSlotElements } from './hooks/useSlotChildren';
|
||||
import { getSlotElements } from './hooks/useSlotChildren';
|
||||
import { useGlobalHandlerMap } from './hooks/useGlobalHandlerMap';
|
||||
import { useEleRef } from './hooks/useEleMap';
|
||||
import { useGridLayout } from './hooks/useGridLayout';
|
||||
|
||||
export const ImplWrapperMain = React.forwardRef<HTMLDivElement, ImplWrapperProps>(
|
||||
(props, ref) => {
|
||||
function ImplWrapperMain(props, ref) {
|
||||
const { component: c, children } = props;
|
||||
const { registry, stateManager } = props.services;
|
||||
|
||||
@ -138,7 +138,32 @@ export const ImplWrapperMain = React.forwardRef<HTMLDivElement, ImplWrapperProps
|
||||
);
|
||||
|
||||
const unmount = traitResults.some(result => result.unmount);
|
||||
const slotElements = useSlotElements(props);
|
||||
const slotElements = useMemo(() => {
|
||||
return getSlotElements({
|
||||
app: props.app,
|
||||
childrenMap: props.childrenMap,
|
||||
children: props.children,
|
||||
component: props.component,
|
||||
gridCallbacks: props.gridCallbacks,
|
||||
services: props.services,
|
||||
hooks: props.hooks,
|
||||
isInModule: props.isInModule,
|
||||
});
|
||||
}, [
|
||||
/**
|
||||
* exclude props.slotProps from dependency,
|
||||
* otherwise, new slotProps will create new slotElements,
|
||||
* which cause extra re-mount
|
||||
*/
|
||||
props.app,
|
||||
props.children,
|
||||
props.childrenMap,
|
||||
props.component,
|
||||
props.gridCallbacks,
|
||||
props.hooks,
|
||||
props.isInModule,
|
||||
props.services,
|
||||
]);
|
||||
|
||||
const C = unmount ? null : (
|
||||
<Impl
|
||||
|
@ -7,7 +7,7 @@ import { ImplWrapperProps, TraitResult } from '../../../types';
|
||||
import { watch } from '../../..';
|
||||
|
||||
export const UnmountImplWrapper = React.forwardRef<HTMLDivElement, ImplWrapperProps>(
|
||||
(props, ref) => {
|
||||
function UnmountImplWrapper(props, ref) {
|
||||
const { component: c, services } = props;
|
||||
const { stateManager, registry } = services;
|
||||
const { executeTrait } = useRuntimeFunctions(props);
|
||||
|
@ -1,13 +1,12 @@
|
||||
import React from 'react';
|
||||
import { RuntimeComponentSchema, SlotSchema } from '@sunmao-ui/core';
|
||||
import { SlotSchema } from '@sunmao-ui/core';
|
||||
import { ImplWrapperProps, SlotsElements } from '../../../../types';
|
||||
import { ImplWrapper } from '../ImplWrapper';
|
||||
|
||||
export function useSlotElements(
|
||||
props: ImplWrapperProps
|
||||
export function getSlotElements(
|
||||
props: ImplWrapperProps & { children?: React.ReactNode }
|
||||
): SlotsElements<Record<string, SlotSchema>> {
|
||||
const { component: c, childrenMap } = props;
|
||||
const childrenCache = new Map<RuntimeComponentSchema, React.ReactElement>();
|
||||
|
||||
if (!childrenMap[c.id]) {
|
||||
return {};
|
||||
@ -15,14 +14,10 @@ export function useSlotElements(
|
||||
const slotElements: SlotsElements<Record<string, SlotSchema>> = {};
|
||||
for (const slot in childrenMap[c.id]) {
|
||||
const slotChildren = childrenMap[c.id][slot].map(child => {
|
||||
if (!childrenCache.get(child)) {
|
||||
const ele = <ImplWrapper key={child.id} {...props} component={child} />;
|
||||
childrenCache.set(child, ele);
|
||||
}
|
||||
return childrenCache.get(child)!;
|
||||
return <ImplWrapper key={child.id} {...props} component={child} />;
|
||||
});
|
||||
|
||||
slotElements[slot] = slotProps => {
|
||||
slotElements[slot] = function inlineSlot(slotProps) {
|
||||
return <>{slotChildren.map(child => React.cloneElement(child, { slotProps }))}</>;
|
||||
};
|
||||
}
|
||||
|
@ -7,7 +7,8 @@ import relativeTime from 'dayjs/plugin/relativeTime';
|
||||
import LocalizedFormat from 'dayjs/plugin/localizedFormat';
|
||||
import { isProxy, reactive, toRaw } from '@vue/reactivity';
|
||||
import { watch } from '../utils/watchReactivity';
|
||||
import { isNumeric, parseExpression, consoleError, ConsoleType, type ExpChunk } from '@sunmao-ui/shared';
|
||||
import { isNumeric, parseExpression, consoleError, ConsoleType } from '@sunmao-ui/shared';
|
||||
import type { ExpChunk } from '@sunmao-ui/shared';
|
||||
|
||||
dayjs.extend(relativeTime);
|
||||
dayjs.extend(isLeapYear);
|
||||
@ -35,7 +36,7 @@ export class ExpressionError extends Error {
|
||||
}
|
||||
}
|
||||
|
||||
export type StateManagerInterface = InstanceType<typeof StateManager>
|
||||
export type StateManagerInterface = InstanceType<typeof StateManager>;
|
||||
|
||||
export class StateManager {
|
||||
store = reactive<Record<string, any>>({});
|
||||
@ -105,9 +106,9 @@ export class StateManager {
|
||||
} catch (error) {
|
||||
if (error instanceof Error) {
|
||||
const expressionError = new ExpressionError(error.message);
|
||||
|
||||
|
||||
if (!noConsoleError) {
|
||||
consoleError(ConsoleType.Expression, '', expressionError.message);
|
||||
consoleError(ConsoleType.Expression, '', expressionError.message);
|
||||
}
|
||||
|
||||
return fallbackWhenError ? fallbackWhenError(raw) : expressionError;
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Type } from '@sinclair/typebox';
|
||||
import { CORE_VERSION, CoreTraitName } from '@sunmao-ui/shared';
|
||||
import { implementRuntimeTrait } from 'src/utils/buildKit';
|
||||
import { implementRuntimeTrait } from '../../utils/buildKit';
|
||||
|
||||
const ContainerPropertySpec = Type.Object({
|
||||
id: Type.String(),
|
||||
|
Loading…
Reference in New Issue
Block a user