fix: component cannot be redisplayed by configuration after rendering is closed

This commit is contained in:
liujuping 2022-03-16 21:51:46 +08:00 committed by LeoYuan 袁力皓
parent d087092fd7
commit c54f369e18
3 changed files with 59 additions and 32 deletions

View File

@ -2,8 +2,10 @@ import { BuiltinSimulatorHost, Node, PropChangeOptions } from '@alilc/lowcode-de
import { GlobalEvent, TransformStage, NodeSchema } from '@alilc/lowcode-types'; import { GlobalEvent, TransformStage, NodeSchema } from '@alilc/lowcode-types';
import { isReactComponent, cloneEnumerableProperty } from '@alilc/lowcode-utils'; import { isReactComponent, cloneEnumerableProperty } from '@alilc/lowcode-utils';
import { EngineOptions } from '@alilc/lowcode-editor-core'; import { EngineOptions } from '@alilc/lowcode-editor-core';
import { debounce } from '../utils/common';
import adapter from '../adapter'; import adapter from '../adapter';
import * as types from '../types/index'; import * as types from '../types/index';
import { parseData } from '../utils';
export interface IComponentHocInfo { export interface IComponentHocInfo {
schema: any; schema: any;
@ -23,7 +25,10 @@ export interface IComponentHocState {
childrenInState: boolean; childrenInState: boolean;
nodeChildren: any; nodeChildren: any;
nodeCacheProps: any; nodeCacheProps: any;
/** 控制是否显示隐藏 */
visible: boolean; visible: boolean;
/** 控制是否渲染 */
condition: boolean;
nodeProps: any; nodeProps: any;
} }
@ -58,7 +63,7 @@ enum RerenderType {
// 缓存 Leaf 层组件,防止重新渲染问题 // 缓存 Leaf 层组件,防止重新渲染问题
class LeafCache { class LeafCache {
constructor(public documentId: string) { constructor(public documentId: string, public device: string) {
} }
/** 组件缓存 */ /** 组件缓存 */
component = new Map(); component = new Map();
@ -140,6 +145,7 @@ export function leafWrapper(Comp: types.IBaseRenderComponent, {
const { engine } = baseRenderer.context; const { engine } = baseRenderer.context;
const host = baseRenderer.props?.__host; const host = baseRenderer.props?.__host;
const curDocumentId = baseRenderer.props?.documentId ?? ''; const curDocumentId = baseRenderer.props?.documentId ?? '';
const curDevice = baseRenderer.props?.device ?? '';
const getNode = baseRenderer.props?.getNode; const getNode = baseRenderer.props?.getNode;
const container: BuiltinSimulatorHost = baseRenderer.props?.__container; const container: BuiltinSimulatorHost = baseRenderer.props?.__container;
const setSchemaChangedSymbol = baseRenderer.props?.setSchemaChangedSymbol; const setSchemaChangedSymbol = baseRenderer.props?.setSchemaChangedSymbol;
@ -152,11 +158,11 @@ export function leafWrapper(Comp: types.IBaseRenderComponent, {
const componentCacheId = schema.id; const componentCacheId = schema.id;
if (!cache || (curDocumentId && curDocumentId !== cache.documentId)) { if (!cache || (curDocumentId && curDocumentId !== cache.documentId) || (curDevice && curDevice !== cache.device)) {
cache?.event.forEach((event) => { cache?.event.forEach(event => {
event.dispose?.forEach((disposeFn: any) => disposeFn && disposeFn()); event.dispose?.forEach((disposeFn: any) => disposeFn && disposeFn());
}); });
cache = new LeafCache(curDocumentId); cache = new LeafCache(curDocumentId, curDevice);
} }
if (!isReactComponent(Comp)) { if (!isReactComponent(Comp)) {
@ -231,11 +237,13 @@ export function leafWrapper(Comp: types.IBaseRenderComponent, {
get defaultState() { get defaultState() {
const { const {
hidden = false, hidden = false,
condition = true,
} = this.leaf?.schema || {}; } = this.leaf?.schema || {};
return { return {
nodeChildren: null, nodeChildren: null,
childrenInState: false, childrenInState: false,
visible: !hidden, visible: !hidden,
condition: parseData(condition, scope),
nodeCacheProps: {}, nodeCacheProps: {},
nodeProps: {}, nodeProps: {},
}; };
@ -285,15 +293,17 @@ export function leafWrapper(Comp: types.IBaseRenderComponent, {
singleRender?: boolean; singleRender?: boolean;
}; };
shouldRenderSingleNode(): boolean { judgeMiniUnitRender() {
if (!this.renderUnitInfo) { if (!this.renderUnitInfo) {
this.getRenderUnitInfo(); this.getRenderUnitInfo();
} }
const { renderUnitInfo } = this; const renderUnitInfo = this.renderUnitInfo || {
singleRender: true,
};
if (renderUnitInfo.singleRender) { if (renderUnitInfo.singleRender) {
return true; return;
} }
const ref = cache.ref.get(renderUnitInfo.minimalUnitId); const ref = cache.ref.get(renderUnitInfo.minimalUnitId);
@ -301,29 +311,32 @@ export function leafWrapper(Comp: types.IBaseRenderComponent, {
if (!ref) { if (!ref) {
__debug('Cant find minimalRenderUnit ref! This make rerender!'); __debug('Cant find minimalRenderUnit ref! This make rerender!');
container.rerender(); container.rerender();
return false; return;
} }
__debug(`${this.leaf?.componentName}(${this.props.componentId}) need render, make its minimalRenderUnit ${renderUnitInfo.minimalUnitName}(${renderUnitInfo.minimalUnitId})`); __debug(`${this.leaf?.componentName}(${this.props.componentId}) need render, make its minimalRenderUnit ${renderUnitInfo.minimalUnitName}(${renderUnitInfo.minimalUnitId})`);
ref.makeUnitRender(); ref.makeUnitRender();
return false;
} }
getRenderUnitInfo(leaf = this.leaf) { getRenderUnitInfo(leaf = this.leaf) {
if (leaf?.isRoot()) { // leaf 在低代码组件中存在 mock 的情况,退出最小渲染单元判断
if (!leaf || typeof leaf.isRoot !== 'function') {
return;
}
if (leaf.isRoot()) {
this.renderUnitInfo = { this.renderUnitInfo = {
singleRender: true, singleRender: true,
...(this.renderUnitInfo || {}), ...(this.renderUnitInfo || {}),
}; };
} }
if (leaf?.componentMeta.isMinimalRenderUnit) { if (leaf.componentMeta.isMinimalRenderUnit) {
this.renderUnitInfo = { this.renderUnitInfo = {
minimalUnitId: leaf.id, minimalUnitId: leaf.id,
minimalUnitName: leaf.componentName, minimalUnitName: leaf.componentName,
singleRender: false, singleRender: false,
}; };
} }
if (leaf?.hasLoop()) { if (leaf.hasLoop()) {
// 含有循环配置的元素,父元素是最小渲染单元 // 含有循环配置的元素,父元素是最小渲染单元
this.renderUnitInfo = { this.renderUnitInfo = {
minimalUnitId: leaf?.parent?.id, minimalUnitId: leaf?.parent?.id,
@ -331,12 +344,13 @@ export function leafWrapper(Comp: types.IBaseRenderComponent, {
singleRender: false, singleRender: false,
}; };
} }
if (leaf?.parent) { if (leaf.parent) {
this.getRenderUnitInfo(leaf.parent); this.getRenderUnitInfo(leaf.parent);
} }
} }
makeUnitRender = () => { // 最小渲染单元做防抖处理
makeUnitRenderDebounced = debounce(() => {
this.beforeRender(RerenderType.MinimalRenderUnit); this.beforeRender(RerenderType.MinimalRenderUnit);
const schema = this.leaf?.export?.(TransformStage.Render); const schema = this.leaf?.export?.(TransformStage.Render);
if (!schema) { if (!schema) {
@ -355,6 +369,10 @@ export function leafWrapper(Comp: types.IBaseRenderComponent, {
__debug(`${this.leaf?.componentName}(${this.props.componentId}) MinimalRenderUnit Render!`); __debug(`${this.leaf?.componentName}(${this.props.componentId}) MinimalRenderUnit Render!`);
this.setState(nextState); this.setState(nextState);
}, 20);
makeUnitRender = () => {
this.makeUnitRenderDebounced();
}; };
componentWillReceiveProps(nextProps: any) { componentWillReceiveProps(nextProps: any) {
@ -389,6 +407,16 @@ export function leafWrapper(Comp: types.IBaseRenderComponent, {
} = propChangeInfo; } = propChangeInfo;
const node = leaf; 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___') { if (key === '___loop___') {
@ -398,9 +426,6 @@ export function leafWrapper(Comp: types.IBaseRenderComponent, {
cache.component.delete(componentCacheId); cache.component.delete(componentCacheId);
return; return;
} }
if (!this.shouldRenderSingleNode()) {
return;
}
this.beforeRender(RerenderType.PropsChanged); this.beforeRender(RerenderType.PropsChanged);
const { state } = this; const { state } = this;
const { nodeCacheProps } = state; const { nodeCacheProps } = state;
@ -419,6 +444,8 @@ export function leafWrapper(Comp: types.IBaseRenderComponent, {
nodeProps, nodeProps,
nodeCacheProps, nodeCacheProps,
}); });
this.judgeMiniUnitRender();
}); });
dispose && this.disposeFunctions.push(dispose); dispose && this.disposeFunctions.push(dispose);
@ -433,15 +460,12 @@ export function leafWrapper(Comp: types.IBaseRenderComponent, {
return; return;
} }
if (!this.shouldRenderSingleNode()) {
return;
}
__debug(`${leaf?.componentName}[${this.props.componentId}] component trigger onVisibleChange(${flag}) event`); __debug(`${leaf?.componentName}[${this.props.componentId}] component trigger onVisibleChange(${flag}) event`);
this.beforeRender(RerenderType.VisibleChanged); this.beforeRender(RerenderType.VisibleChanged);
this.setState({ this.setState({
visible: flag, visible: flag,
}); });
this.judgeMiniUnitRender();
}); });
dispose && this.disposeFunctions.push(dispose); dispose && this.disposeFunctions.push(dispose);
@ -456,26 +480,23 @@ export function leafWrapper(Comp: types.IBaseRenderComponent, {
type, type,
node, node,
} = param || {}; } = param || {};
if (!this.shouldRenderSingleNode()) {
return;
}
this.beforeRender(`${RerenderType.ChildChanged}-${type}`, node); this.beforeRender(`${RerenderType.ChildChanged}-${type}`, node);
// TODO: 缓存同级其他元素的 children。 // TODO: 缓存同级其他元素的 children。
// 缓存二级 children Next 查询筛选组件有问题 // 缓存二级 children Next 查询筛选组件有问题
// 缓存一级 children Next Tab 组件有问题 // 缓存一级 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); __debug(`${schema.componentName}[${this.props.componentId}] component trigger onChildrenChange event`, nextChild);
this.setState({ this.setState({
nodeChildren: nextChild, nodeChildren: nextChild,
childrenInState: true, childrenInState: true,
}); });
this.judgeMiniUnitRender();
}); });
dispose && this.disposeFunctions.push(dispose); dispose && this.disposeFunctions.push(dispose);
} }
componentWillUnmount() { componentWillUnmount() {
this.disposeFunctions.forEach((fn) => fn()); this.disposeFunctions.forEach(fn => fn());
} }
get hasChildren(): boolean { get hasChildren(): boolean {
@ -509,7 +530,7 @@ export function leafWrapper(Comp: types.IBaseRenderComponent, {
} }
render() { render() {
if (!this.state.visible) { if (!this.state.visible || !this.state.condition) {
return null; return null;
} }

View File

@ -467,8 +467,10 @@ export default function baseRendererFactory(): IBaseRenderComponent {
otherProps.__componentName = schema.componentName; 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; return null;
} }
@ -488,7 +490,7 @@ export default function baseRendererFactory(): IBaseRenderComponent {
} }
} }
const condition = schema.condition == null ? true : parseData(schema.condition, scope); const condition = schema.condition == null ? true : parseData(schema.condition, scope);
if (!condition) return null; if (!condition && !displayInHook) return null;
let scopeKey = ''; let scopeKey = '';
// 判断组件是否需要生成scope且只生成一次挂在this.__compScopes上 // 判断组件是否需要生成scope且只生成一次挂在this.__compScopes上

View File

@ -157,6 +157,10 @@ export interface IBaseRendererProps {
setSchemaChangedSymbol?: (symbol: boolean) => void; setSchemaChangedSymbol?: (symbol: boolean) => void;
documentId?: string; documentId?: string;
getNode?: any; getNode?: any;
/**
* 'default'
*/
device?: 'default' | 'mobile' | string;
} }
export interface IInfo { export interface IInfo {