diff --git a/packages/renderer-core/src/hoc/leaf.tsx b/packages/renderer-core/src/hoc/leaf.tsx index ac68caafd..8d9681362 100644 --- a/packages/renderer-core/src/hoc/leaf.tsx +++ b/packages/renderer-core/src/hoc/leaf.tsx @@ -2,8 +2,10 @@ import { BuiltinSimulatorHost, Node, PropChangeOptions } from '@alilc/lowcode-de import { GlobalEvent, TransformStage, NodeSchema } from '@alilc/lowcode-types'; import { isReactComponent, cloneEnumerableProperty } from '@alilc/lowcode-utils'; import { EngineOptions } from '@alilc/lowcode-editor-core'; +import { debounce } from '../utils/common'; import adapter from '../adapter'; import * as types from '../types/index'; +import { parseData } from '../utils'; export interface IComponentHocInfo { schema: any; @@ -23,7 +25,10 @@ export interface IComponentHocState { childrenInState: boolean; nodeChildren: any; nodeCacheProps: any; + /** 控制是否显示隐藏 */ visible: boolean; + /** 控制是否渲染 */ + condition: boolean; nodeProps: any; } @@ -58,7 +63,7 @@ enum RerenderType { // 缓存 Leaf 层组件,防止重新渲染问题 class LeafCache { - constructor(public documentId: string) { + constructor(public documentId: string, public device: string) { } /** 组件缓存 */ component = new Map(); @@ -140,6 +145,7 @@ export function leafWrapper(Comp: types.IBaseRenderComponent, { const { engine } = baseRenderer.context; const host = baseRenderer.props?.__host; const curDocumentId = baseRenderer.props?.documentId ?? ''; + const curDevice = baseRenderer.props?.device ?? ''; const getNode = baseRenderer.props?.getNode; const container: BuiltinSimulatorHost = baseRenderer.props?.__container; const setSchemaChangedSymbol = baseRenderer.props?.setSchemaChangedSymbol; @@ -152,11 +158,11 @@ export function leafWrapper(Comp: types.IBaseRenderComponent, { const componentCacheId = schema.id; - if (!cache || (curDocumentId && curDocumentId !== cache.documentId)) { - cache?.event.forEach((event) => { + if (!cache || (curDocumentId && curDocumentId !== cache.documentId) || (curDevice && curDevice !== cache.device)) { + cache?.event.forEach(event => { event.dispose?.forEach((disposeFn: any) => disposeFn && disposeFn()); }); - cache = new LeafCache(curDocumentId); + cache = new LeafCache(curDocumentId, curDevice); } if (!isReactComponent(Comp)) { @@ -231,11 +237,13 @@ export function leafWrapper(Comp: types.IBaseRenderComponent, { get defaultState() { const { hidden = false, + condition = true, } = this.leaf?.schema || {}; return { nodeChildren: null, childrenInState: false, visible: !hidden, + condition: parseData(condition, scope), nodeCacheProps: {}, nodeProps: {}, }; @@ -285,15 +293,17 @@ export function leafWrapper(Comp: types.IBaseRenderComponent, { singleRender?: boolean; }; - shouldRenderSingleNode(): boolean { + judgeMiniUnitRender() { if (!this.renderUnitInfo) { this.getRenderUnitInfo(); } - const { renderUnitInfo } = this; + const renderUnitInfo = this.renderUnitInfo || { + singleRender: true, + }; if (renderUnitInfo.singleRender) { - return true; + return; } const ref = cache.ref.get(renderUnitInfo.minimalUnitId); @@ -301,29 +311,32 @@ export function leafWrapper(Comp: types.IBaseRenderComponent, { if (!ref) { __debug('Cant find minimalRenderUnit ref! This make rerender!'); container.rerender(); - return false; + return; } __debug(`${this.leaf?.componentName}(${this.props.componentId}) need render, make its minimalRenderUnit ${renderUnitInfo.minimalUnitName}(${renderUnitInfo.minimalUnitId})`); ref.makeUnitRender(); - - return false; } getRenderUnitInfo(leaf = this.leaf) { - if (leaf?.isRoot()) { + // leaf 在低代码组件中存在 mock 的情况,退出最小渲染单元判断 + if (!leaf || typeof leaf.isRoot !== 'function') { + return; + } + + if (leaf.isRoot()) { this.renderUnitInfo = { singleRender: true, ...(this.renderUnitInfo || {}), }; } - if (leaf?.componentMeta.isMinimalRenderUnit) { + if (leaf.componentMeta.isMinimalRenderUnit) { this.renderUnitInfo = { minimalUnitId: leaf.id, minimalUnitName: leaf.componentName, singleRender: false, }; } - if (leaf?.hasLoop()) { + if (leaf.hasLoop()) { // 含有循环配置的元素,父元素是最小渲染单元 this.renderUnitInfo = { minimalUnitId: leaf?.parent?.id, @@ -331,12 +344,13 @@ export function leafWrapper(Comp: types.IBaseRenderComponent, { singleRender: false, }; } - if (leaf?.parent) { + if (leaf.parent) { this.getRenderUnitInfo(leaf.parent); } } - makeUnitRender = () => { + // 最小渲染单元做防抖处理 + makeUnitRenderDebounced = debounce(() => { this.beforeRender(RerenderType.MinimalRenderUnit); const schema = this.leaf?.export?.(TransformStage.Render); if (!schema) { @@ -355,6 +369,10 @@ export function leafWrapper(Comp: types.IBaseRenderComponent, { __debug(`${this.leaf?.componentName}(${this.props.componentId}) MinimalRenderUnit Render!`); this.setState(nextState); + }, 20); + + makeUnitRender = () => { + this.makeUnitRenderDebounced(); }; componentWillReceiveProps(nextProps: any) { @@ -389,6 +407,16 @@ export function leafWrapper(Comp: types.IBaseRenderComponent, { } = propChangeInfo; const node = leaf; + if (key === '___condition___') { + const condition = parseData(newValue, scope); + __debug(`key is ___condition___, change condition value to [${condition}]`); + // 条件表达式改变 + this.setState({ + condition, + }); + return; + } + // 如果循坏条件变化,从根节点重新渲染 // 目前多层循坏无法判断需要从哪一层开始渲染,故先粗暴解决 if (key === '___loop___') { @@ -398,9 +426,6 @@ export function leafWrapper(Comp: types.IBaseRenderComponent, { cache.component.delete(componentCacheId); return; } - if (!this.shouldRenderSingleNode()) { - return; - } this.beforeRender(RerenderType.PropsChanged); const { state } = this; const { nodeCacheProps } = state; @@ -419,6 +444,8 @@ export function leafWrapper(Comp: types.IBaseRenderComponent, { nodeProps, nodeCacheProps, }); + + this.judgeMiniUnitRender(); }); dispose && this.disposeFunctions.push(dispose); @@ -433,15 +460,12 @@ export function leafWrapper(Comp: types.IBaseRenderComponent, { return; } - if (!this.shouldRenderSingleNode()) { - return; - } - __debug(`${leaf?.componentName}[${this.props.componentId}] component trigger onVisibleChange(${flag}) event`); this.beforeRender(RerenderType.VisibleChanged); this.setState({ visible: flag, }); + this.judgeMiniUnitRender(); }); dispose && this.disposeFunctions.push(dispose); @@ -456,26 +480,23 @@ export function leafWrapper(Comp: types.IBaseRenderComponent, { type, node, } = param || {}; - if (!this.shouldRenderSingleNode()) { - return; - } this.beforeRender(`${RerenderType.ChildChanged}-${type}`, node); // TODO: 缓存同级其他元素的 children。 // 缓存二级 children Next 查询筛选组件有问题 // 缓存一级 children Next Tab 组件有问题 - const nextChild = getChildren(leaf?.export?.(TransformStage.Render) as NodeSchema, scope, Comp); // this.childrenMap + const nextChild = getChildren(leaf?.export?.(TransformStage.Render) as types.ISchema, scope, Comp); // this.childrenMap __debug(`${schema.componentName}[${this.props.componentId}] component trigger onChildrenChange event`, nextChild); this.setState({ nodeChildren: nextChild, childrenInState: true, }); + this.judgeMiniUnitRender(); }); - dispose && this.disposeFunctions.push(dispose); } componentWillUnmount() { - this.disposeFunctions.forEach((fn) => fn()); + this.disposeFunctions.forEach(fn => fn()); } get hasChildren(): boolean { @@ -509,7 +530,7 @@ export function leafWrapper(Comp: types.IBaseRenderComponent, { } render() { - if (!this.state.visible) { + if (!this.state.visible || !this.state.condition) { return null; } diff --git a/packages/renderer-core/src/renderer/base.tsx b/packages/renderer-core/src/renderer/base.tsx index 001e5f06d..82d2884e1 100644 --- a/packages/renderer-core/src/renderer/base.tsx +++ b/packages/renderer-core/src/renderer/base.tsx @@ -467,8 +467,10 @@ export default function baseRendererFactory(): IBaseRenderComponent { otherProps.__componentName = schema.componentName; } - if (schema.hidden && (engine?.props?.designMode && engine?.props?.designMode !== 'design')) { - // designMode 为 design 情况下,需要进入 leaf Hoc,进行相关事件注册 + // DesignMode 为 design 情况下,需要进入 leaf Hoc,进行相关事件注册 + const displayInHook = engine?.props?.designMode === 'design'; + + if (schema.hidden && !displayInHook) { return null; } @@ -488,7 +490,7 @@ export default function baseRendererFactory(): IBaseRenderComponent { } } const condition = schema.condition == null ? true : parseData(schema.condition, scope); - if (!condition) return null; + if (!condition && !displayInHook) return null; let scopeKey = ''; // 判断组件是否需要生成scope,且只生成一次,挂在this.__compScopes上 diff --git a/packages/renderer-core/src/types/index.ts b/packages/renderer-core/src/types/index.ts index 5c8f7e1bf..e85602c7b 100644 --- a/packages/renderer-core/src/types/index.ts +++ b/packages/renderer-core/src/types/index.ts @@ -157,6 +157,10 @@ export interface IBaseRendererProps { setSchemaChangedSymbol?: (symbol: boolean) => void; documentId?: string; getNode?: any; + /** + * 设备类型,默认值:'default' + */ + device?: 'default' | 'mobile' | string; } export interface IInfo {