From 67473315296eeed570997bd2852d1377a0978f46 Mon Sep 17 00:00:00 2001 From: Dunqing Date: Wed, 29 Mar 2023 17:11:20 +0800 Subject: [PATCH] refactor: improve FixedBlock performance (#1593) * refactor: improve FixedBlock performance * fix: style * fix: fixedBlock not work when the page have many blocks * refactor: improve performance --- .../block-provider/CalendarBlockProvider.tsx | 31 +++-- .../block-provider/KanbanBlockProvider.tsx | 33 ++--- .../src/block-provider/TableBlockProvider.tsx | 37 ++--- .../antd/form-item/FormItem.tsx | 3 + .../schema-component/antd/page/FixedBlock.tsx | 130 ++++++++---------- .../src/schema-component/antd/page/Page.tsx | 25 ++-- .../map/src/client/block/MapBlockProvider.tsx | 36 ++--- 7 files changed, 145 insertions(+), 150 deletions(-) diff --git a/packages/core/client/src/block-provider/CalendarBlockProvider.tsx b/packages/core/client/src/block-provider/CalendarBlockProvider.tsx index d94557b71..bf4ebdadc 100644 --- a/packages/core/client/src/block-provider/CalendarBlockProvider.tsx +++ b/packages/core/client/src/block-provider/CalendarBlockProvider.tsx @@ -1,7 +1,7 @@ import { ArrayField } from '@formily/core'; import { useField } from '@formily/react'; import React, { createContext, useContext, useEffect } from 'react'; -import { useFixedSchema } from '../schema-component'; +import { FixedBlockWrapper } from '../schema-component'; import { BlockProvider, useBlockRequestContext } from './BlockProvider'; export const CalendarBlockContext = createContext({}); @@ -10,23 +10,24 @@ const InternalCalendarBlockProvider = (props) => { const { fieldNames, showLunar } = props; const field = useField(); const { resource, service } = useBlockRequestContext(); - const fixedBlock = useFixedSchema() // if (service.loading) { // return ; // } return ( - - {props.children} - + + + {props.children} + + ); }; @@ -53,6 +54,6 @@ export const useCalendarBlockProps = () => { return { fieldNames: ctx.fieldNames, showLunar: ctx.showLunar, - fixedBlock: ctx.fixedBlock + fixedBlock: ctx.fixedBlock, }; }; diff --git a/packages/core/client/src/block-provider/KanbanBlockProvider.tsx b/packages/core/client/src/block-provider/KanbanBlockProvider.tsx index e08bd7867..c6ae44b9f 100644 --- a/packages/core/client/src/block-provider/KanbanBlockProvider.tsx +++ b/packages/core/client/src/block-provider/KanbanBlockProvider.tsx @@ -5,7 +5,7 @@ import uniq from 'lodash/uniq'; import React, { createContext, useContext, useEffect } from 'react'; import { useACLRoleContext } from '../acl'; import { useCollection, useCollectionManager } from '../collection-manager'; -import { useFixedSchema } from '../schema-component'; +import { FixedBlockWrapper } from '../schema-component'; import { toColumns } from '../schema-component/antd/kanban/Kanban'; import { BlockProvider, useBlockRequestContext } from './BlockProvider'; @@ -24,7 +24,6 @@ const useGroupField = (props) => { const InternalKanbanBlockProvider = (props) => { const field = useField(); - const fixedBlock = useFixedSchema(); const { resource, service } = useBlockRequestContext(); const groupField = useGroupField(props); if (!groupField) { @@ -35,20 +34,22 @@ const InternalKanbanBlockProvider = (props) => { } field.loaded = true; return ( - - {props.children} - + + + {props.children} + + ); }; diff --git a/packages/core/client/src/block-provider/TableBlockProvider.tsx b/packages/core/client/src/block-provider/TableBlockProvider.tsx index da3e49117..461f340f3 100644 --- a/packages/core/client/src/block-provider/TableBlockProvider.tsx +++ b/packages/core/client/src/block-provider/TableBlockProvider.tsx @@ -3,7 +3,7 @@ import { FormContext, Schema, useField, useFieldSchema } from '@formily/react'; import uniq from 'lodash/uniq'; import React, { createContext, useContext, useEffect, useMemo, useState } from 'react'; import { useCollectionManager } from '../collection-manager'; -import { SchemaComponentOptions, useFixedSchema, removeNullCondition } from '../schema-component'; +import { SchemaComponentOptions, removeNullCondition, FixedBlockWrapper } from '../schema-component'; import { BlockProvider, RenderChildrenWithAssociationFilter, useBlockRequestContext } from './BlockProvider'; import { useFilterBlock } from '../filter-provider/FilterProvider'; import { findFilterTargets } from './hooks'; @@ -24,24 +24,25 @@ const InternalTableBlockProvider = (props: Props) => { const field = useField(); const { resource, service } = useBlockRequestContext(); const [expandFlag, setExpandFlag] = useState(false); - useFixedSchema(); return ( - setExpandFlag(!expandFlag), - }} - > - - + + setExpandFlag(!expandFlag), + }} + > + + + ); }; diff --git a/packages/core/client/src/schema-component/antd/form-item/FormItem.tsx b/packages/core/client/src/schema-component/antd/form-item/FormItem.tsx index 8e7dec4c7..78839c714 100644 --- a/packages/core/client/src/schema-component/antd/form-item/FormItem.tsx +++ b/packages/core/client/src/schema-component/antd/form-item/FormItem.tsx @@ -20,6 +20,9 @@ const divWrap = (schema: ISchema) => { return { type: 'void', 'x-component': 'div', + 'x-component-props': { + className: 'nb-block-wrap', + }, properties: { [schema.name || uid()]: schema, }, diff --git a/packages/core/client/src/schema-component/antd/page/FixedBlock.tsx b/packages/core/client/src/schema-component/antd/page/FixedBlock.tsx index dc192dfc0..4a78de9cc 100644 --- a/packages/core/client/src/schema-component/antd/page/FixedBlock.tsx +++ b/packages/core/client/src/schema-component/antd/page/FixedBlock.tsx @@ -1,51 +1,58 @@ import React, { useContext, useEffect, useMemo, useRef, useState } from 'react'; -import { RecursionField, Schema, useField, useFieldSchema } from '@formily/react'; +import { useField, useFieldSchema } from '@formily/react'; import { css } from '@emotion/css'; import { SchemaSettings } from '../../../schema-settings'; import { useTranslation } from 'react-i18next'; import { useDesignable } from '../../hooks'; import { useRecord } from '../../../record-provider'; -import { useBlockTemplateContext } from '../../../schema-templates/BlockTemplate'; -const FixedBlockContext = React.createContext({ - setFixedSchema: (schema: Schema) => {}, +const FixedBlockContext = React.createContext<{ + setFixedBlock: (value: string | false) => void; + height: number; + fixedBlockUID: boolean | string; +}>({ + setFixedBlock: () => {}, height: 0, - fixedSchemaRef: {} as unknown as React.MutableRefObject, + fixedBlockUID: false, }); export const useFixedSchema = () => { const field = useField(); const fieldSchema = useFieldSchema(); - const { setFixedSchema, fixedSchemaRef } = useFixedBlock(); - const { fieldSchema: templateFieldSchema } = useBlockTemplateContext(); + const { setFixedBlock, fixedBlockUID } = useFixedBlock(); const hasSet = useRef(false); useEffect(() => { - if (fieldSchema?.['x-decorator-props']?.fixedBlock) { - const nextSchema = templateFieldSchema || fieldSchema; - setFixedSchema(nextSchema); + if (!fixedBlockUID || hasSet.current) { + setFixedBlock(field?.decoratorProps?.fixedBlock ? fieldSchema['x-uid'] : false); hasSet.current = true; - } else if (hasSet.current) { - setFixedSchema(null); } - }, [field?.decoratorProps?.fixedBlock, fieldSchema?.['x-decorator-props']?.fixedBlock]); + }, [field?.decoratorProps?.fixedBlock]); - useEffect( - () => () => { - if (hasSet.current && fixedSchemaRef.current) { - setFixedSchema(null); - fixedSchemaRef.current = null; - } - }, - [], - ); - return fieldSchema?.['x-decorator-props']?.fixedBlock + return fieldSchema['x-uid'] === fixedBlockUID; }; export const useFixedBlock = () => { return useContext(FixedBlockContext); }; +export const FixedBlockWrapper: React.FC = (props) => { + const fixedBlock = useFixedSchema(); + const { height, fixedBlockUID } = useFixedBlock(); + // The fixedBlockUID of false means that the page has no fixed blocks + if (!fixedBlock && fixedBlockUID) return null; + return ( +
+ {props.children} +
+ ); +}; + export const useFixedBlockDesignerSetting = () => { const field = useField(); const { t } = useTranslation(); @@ -83,56 +90,39 @@ interface FixedBlockProps { height: number; } +const fixedBlockCss = css` + overflow: hidden; + position: relative; + .noco-card-item { + height: 100%; + .ant-card { + display: flex; + flex-direction: column; + height: 100%; + .ant-card-body { + height: 1px; + flex: 1; + display: flex; + flex-direction: column; + overflow: hidden; + } + } + } +`; + const FixedBlock: React.FC = (props) => { const { height } = props; - const [fixedSchema, _setFixedSchema] = useState(); - const fixedSchemaRef = useRef(fixedSchema); - - const setFixedSchema = (next) => { - if (fixedSchema && next) { - fixedSchemaRef.current = next; - } - _setFixedSchema(next); - }; - - const schema = useMemo(() => { - return fixedSchema?.parent; - }, [fixedSchema]); - + const [fixedBlockUID, setFixedBlock] = useState(false); return ( - - {schema ? ( -
- -
- ) : ( - props.children - )} + +
+ {props.children} +
); }; diff --git a/packages/core/client/src/schema-component/antd/page/Page.tsx b/packages/core/client/src/schema-component/antd/page/Page.tsx index 6d7ac076e..b4824c700 100644 --- a/packages/core/client/src/schema-component/antd/page/Page.tsx +++ b/packages/core/client/src/schema-component/antd/page/Page.tsx @@ -111,13 +111,22 @@ const pageDesignerCss = css` } `; +const pageWithFixedBlockCss = classNames([ + 'nb-page', + css` + > .nb-grid:not(:last-child) { + > .nb-schema-initializer-button { + display: none; + } + } + `, +]); + export const Page = (props) => { const { children, ...others } = props; - const field = useField(); const compile = useCompile(); const { title, setTitle } = useDocumentTitle(); const fieldSchema = useFieldSchema(); - const history = useHistory(); const dn = useDesignable(); useEffect(() => { if (!title) { @@ -288,17 +297,7 @@ export const Page = (props) => { height + 46 + 48 } > -
.nb-grid:not(:last-child) { - > .nb-schema-initializer-button { - display: none; - } - } - `} - > - {props.children} -
+
{props.children}
)} diff --git a/packages/plugins/map/src/client/block/MapBlockProvider.tsx b/packages/plugins/map/src/client/block/MapBlockProvider.tsx index 2348f9948..cddbecffd 100644 --- a/packages/plugins/map/src/client/block/MapBlockProvider.tsx +++ b/packages/plugins/map/src/client/block/MapBlockProvider.tsx @@ -1,6 +1,5 @@ -import { ArrayField } from '@formily/core'; import { useField, useFieldSchema } from '@formily/react'; -import { BlockProvider, SchemaComponentOptions, useBlockRequestContext, useFixedSchema } from '@nocobase/client'; +import { BlockProvider, FixedBlockWrapper, SchemaComponentOptions, useBlockRequestContext } from '@nocobase/client'; import React, { createContext, useContext, useEffect, useState } from 'react'; export const MapBlockContext = createContext({}); @@ -12,23 +11,24 @@ const InternalMapBlockProvider = (props) => { const { resource, service } = useBlockRequestContext(); const [selectedRecordKeys, setSelectedRecordKeys] = useState([]); - useFixedSchema(); return ( - - - {props.children} - - + + + + {props.children} + + + ); };