mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2025-12-12 11:20:11 +00:00
fix: component cannot be redisplayed by configuration after rendering is closed
This commit is contained in:
parent
d087092fd7
commit
c54f369e18
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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上
|
||||
|
||||
@ -157,6 +157,10 @@ export interface IBaseRendererProps {
|
||||
setSchemaChangedSymbol?: (symbol: boolean) => void;
|
||||
documentId?: string;
|
||||
getNode?: any;
|
||||
/**
|
||||
* 设备类型,默认值:'default'
|
||||
*/
|
||||
device?: 'default' | 'mobile' | string;
|
||||
}
|
||||
|
||||
export interface IInfo {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user