mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2026-01-12 17:08:14 +00:00
fix: doc import 时临时关闭 Node 相关事件监听
This commit is contained in:
parent
d846e86472
commit
0f34f2702d
@ -28,8 +28,6 @@ module.exports = {
|
||||
'eol-last': 0,
|
||||
'react/no-find-dom-node': 0,
|
||||
'no-case-declarations': 0,
|
||||
'@typescript-eslint/indent': 0,
|
||||
"indent": "off",
|
||||
"@typescript-eslint/indent": ["error", 2]
|
||||
'@typescript-eslint/indent': 0
|
||||
}
|
||||
};
|
||||
|
||||
@ -71,6 +71,8 @@ export class SettingTopEntry implements SettingEntry {
|
||||
|
||||
readonly designer: Designer;
|
||||
|
||||
disposeFunctions: any[] = [];
|
||||
|
||||
constructor(readonly editor: IEditor, readonly nodes: Node[]) {
|
||||
if (!Array.isArray(nodes) || nodes.length < 1) {
|
||||
throw new ReferenceError('nodes should not be empty');
|
||||
@ -85,7 +87,7 @@ export class SettingTopEntry implements SettingEntry {
|
||||
// clear fields
|
||||
this.setupItems();
|
||||
|
||||
this.setupEvents();
|
||||
this.disposeFunctions.push(this.setupEvents());
|
||||
}
|
||||
|
||||
private setupComponentMeta() {
|
||||
@ -127,7 +129,7 @@ export class SettingTopEntry implements SettingEntry {
|
||||
}
|
||||
|
||||
private setupEvents() {
|
||||
this.componentMeta?.onMetadataChange(() => {
|
||||
return this.componentMeta?.onMetadataChange(() => {
|
||||
this.setupItems();
|
||||
});
|
||||
}
|
||||
@ -219,6 +221,8 @@ export class SettingTopEntry implements SettingEntry {
|
||||
this.disposeItems();
|
||||
this._settingFieldMap = {};
|
||||
this.emitter.removeAllListeners();
|
||||
this.disposeFunctions.forEach(f => f());
|
||||
this.disposeFunctions = [];
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { computed, makeObservable, obx, action } from '@ali/lowcode-editor-core';
|
||||
import { computed, makeObservable, obx, action, runWithGlobalEventOff, wrapWithEventSwitch } from '@ali/lowcode-editor-core';
|
||||
import { NodeData, isJSExpression, isDOMText, NodeSchema, isNodeSchema, RootSchema, PageSchema } from '@ali/lowcode-types';
|
||||
import { EventEmitter } from 'events';
|
||||
import { Project } from '../project';
|
||||
@ -361,17 +361,19 @@ export class DocumentModel {
|
||||
@action
|
||||
import(schema: RootSchema, checkId = false) {
|
||||
const drillDownNodeId = this._drillDownNode?.id;
|
||||
// TODO: 暂时用饱和式删除,原因是 Slot 节点并不是树节点,无法正常递归删除
|
||||
this.nodes.forEach(node => {
|
||||
if (node.isRoot()) return;
|
||||
this.internalRemoveAndPurgeNode(node, true);
|
||||
});
|
||||
this.rootNode?.import(schema as any, checkId);
|
||||
runWithGlobalEventOff(() => {
|
||||
// TODO: 暂时用饱和式删除,原因是 Slot 节点并不是树节点,无法正常递归删除
|
||||
this.nodes.forEach(node => {
|
||||
if (node.isRoot()) return;
|
||||
this.internalRemoveAndPurgeNode(node, true);
|
||||
});
|
||||
this.rootNode?.import(schema as any, checkId);
|
||||
|
||||
// todo: select added and active track added
|
||||
if (drillDownNodeId) {
|
||||
this.drillDown(this.getNode(drillDownNodeId));
|
||||
}
|
||||
// todo: select added and active track added
|
||||
if (drillDownNodeId) {
|
||||
this.drillDown(this.getNode(drillDownNodeId));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export(stage: TransformStage = TransformStage.Serilize) {
|
||||
@ -699,16 +701,18 @@ export class DocumentModel {
|
||||
}
|
||||
|
||||
onNodeCreate(func: (node: Node) => void) {
|
||||
this.emitter.on('nodecreate', func);
|
||||
const wrappedFunc = wrapWithEventSwitch(func);
|
||||
this.emitter.on('nodecreate', wrappedFunc);
|
||||
return () => {
|
||||
this.emitter.removeListener('nodecreate', func);
|
||||
this.emitter.removeListener('nodecreate', wrappedFunc);
|
||||
};
|
||||
}
|
||||
|
||||
onNodeDestroy(func: (node: Node) => void) {
|
||||
this.emitter.on('nodedestroy', func);
|
||||
const wrappedFunc = wrapWithEventSwitch(func);
|
||||
this.emitter.on('nodedestroy', wrappedFunc);
|
||||
return () => {
|
||||
this.emitter.removeListener('nodedestroy', func);
|
||||
this.emitter.removeListener('nodedestroy', wrappedFunc);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { ReactElement } from 'react';
|
||||
import { EventEmitter } from 'events';
|
||||
import { obx, computed, autorun, makeObservable, runInAction, getObserverTree } from '@ali/lowcode-editor-core';
|
||||
import { obx, computed, autorun, makeObservable, runInAction, wrapWithEventSwitch } from '@ali/lowcode-editor-core';
|
||||
import {
|
||||
isDOMText,
|
||||
isJSExpression,
|
||||
@ -560,9 +560,10 @@ export class Node<Schema extends NodeSchema = NodeSchema> {
|
||||
}
|
||||
|
||||
onVisibleChange(func: (flag: boolean) => any): () => void {
|
||||
this.emitter.on('visibleChange', func);
|
||||
const wrappedFunc = wrapWithEventSwitch(func);
|
||||
this.emitter.on('visibleChange', wrappedFunc);
|
||||
return () => {
|
||||
this.emitter.removeListener('visibleChange', func);
|
||||
this.emitter.removeListener('visibleChange', wrappedFunc);
|
||||
};
|
||||
}
|
||||
|
||||
@ -920,7 +921,8 @@ export class Node<Schema extends NodeSchema = NodeSchema> {
|
||||
}
|
||||
|
||||
onChildrenChange(fn: (param?: { type: string, node: Node }) => void): (() => void) | undefined {
|
||||
return this.children?.onChange(fn);
|
||||
const wrappedFunc = wrapWithEventSwitch(fn);
|
||||
return this.children?.onChange(wrappedFunc);
|
||||
}
|
||||
|
||||
mergeChildren(
|
||||
@ -1118,9 +1120,10 @@ export class Node<Schema extends NodeSchema = NodeSchema> {
|
||||
}
|
||||
|
||||
onPropChange(func: (info: PropChangeOptions) => void): Function {
|
||||
this.emitter.on('propChange', func);
|
||||
const wrappedFunc = wrapWithEventSwitch(func);
|
||||
this.emitter.on('propChange', wrappedFunc);
|
||||
return () => {
|
||||
this.emitter.removeListener('propChange', func);
|
||||
this.emitter.removeListener('propChange', wrappedFunc);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -180,7 +180,7 @@ Object {
|
||||
"labelTextAlign": "right",
|
||||
"labelTipsIcon": "",
|
||||
"labelTipsText": Object {
|
||||
"en_US": "",
|
||||
"en_US": null,
|
||||
"type": "i18n",
|
||||
"use": "zh_CN",
|
||||
"zh_CN": "",
|
||||
@ -259,7 +259,7 @@ Object {
|
||||
"labelTextAlign": "right",
|
||||
"labelTipsIcon": "",
|
||||
"labelTipsText": Object {
|
||||
"en_US": "",
|
||||
"en_US": null,
|
||||
"type": "i18n",
|
||||
"use": "zh_CN",
|
||||
"zh_CN": "",
|
||||
@ -334,7 +334,7 @@ Object {
|
||||
"labelTextAlign": "right",
|
||||
"labelTipsIcon": "",
|
||||
"labelTipsText": Object {
|
||||
"en_US": "",
|
||||
"en_US": null,
|
||||
"type": "i18n",
|
||||
"use": "zh_CN",
|
||||
"zh_CN": "",
|
||||
@ -426,7 +426,7 @@ Object {
|
||||
"labelTextAlign": "right",
|
||||
"labelTipsIcon": "",
|
||||
"labelTipsText": Object {
|
||||
"en_US": "",
|
||||
"en_US": null,
|
||||
"type": "i18n",
|
||||
"use": "zh_CN",
|
||||
"zh_CN": "",
|
||||
@ -517,7 +517,7 @@ Object {
|
||||
"labelTextAlign": "right",
|
||||
"labelTipsIcon": "",
|
||||
"labelTipsText": Object {
|
||||
"en_US": "",
|
||||
"en_US": null,
|
||||
"type": "i18n",
|
||||
"use": "zh_CN",
|
||||
"zh_CN": "",
|
||||
@ -684,7 +684,7 @@ Object {
|
||||
"labelTextAlign": "right",
|
||||
"labelTipsIcon": "",
|
||||
"labelTipsText": Object {
|
||||
"en_US": "",
|
||||
"en_US": null,
|
||||
"type": "i18n",
|
||||
"use": "zh_CN",
|
||||
"zh_CN": "",
|
||||
@ -763,7 +763,7 @@ Object {
|
||||
"labelTextAlign": "right",
|
||||
"labelTipsIcon": "",
|
||||
"labelTipsText": Object {
|
||||
"en_US": "",
|
||||
"en_US": null,
|
||||
"type": "i18n",
|
||||
"use": "zh_CN",
|
||||
"zh_CN": "",
|
||||
@ -855,7 +855,7 @@ Object {
|
||||
"labelTextAlign": "right",
|
||||
"labelTipsIcon": "",
|
||||
"labelTipsText": Object {
|
||||
"en_US": "",
|
||||
"en_US": null,
|
||||
"type": "i18n",
|
||||
"use": "zh_CN",
|
||||
"zh_CN": "",
|
||||
|
||||
30
packages/editor-core/src/utils/control.ts
Normal file
30
packages/editor-core/src/utils/control.ts
Normal file
@ -0,0 +1,30 @@
|
||||
let globalEventOn = true;
|
||||
|
||||
export function setGlobalEventFlag(flag: boolean) {
|
||||
globalEventOn = flag;
|
||||
}
|
||||
|
||||
export function switchGlobalEventOn() {
|
||||
setGlobalEventFlag(true);
|
||||
}
|
||||
|
||||
export function switchGlobalEventOff() {
|
||||
setGlobalEventFlag(false);
|
||||
}
|
||||
|
||||
export function isGlobalEventOn() {
|
||||
return globalEventOn;
|
||||
}
|
||||
|
||||
export function runWithGlobalEventOff(fn: Function) {
|
||||
switchGlobalEventOff();
|
||||
fn();
|
||||
switchGlobalEventOn();
|
||||
}
|
||||
|
||||
type ListenerFunc = (...args: any[]) => void;
|
||||
export function wrapWithEventSwitch(fn: ListenerFunc): ListenerFunc {
|
||||
return (...args: any[]) => {
|
||||
if (isGlobalEventOn()) fn(...args);
|
||||
};
|
||||
}
|
||||
@ -3,3 +3,4 @@ export * from './monitor';
|
||||
export * from './obx';
|
||||
export * from './request';
|
||||
export * from './focus-tracker';
|
||||
export * from './control';
|
||||
|
||||
@ -90,7 +90,6 @@ export function leafWrapper(Comp: types.IBaseRenderer, {
|
||||
type?: string;
|
||||
node?: Node;
|
||||
} = {};
|
||||
|
||||
static displayName = schema.componentName;
|
||||
|
||||
disposeFunctions: ((() => void) | Function)[] = [];
|
||||
@ -140,19 +139,44 @@ export function leafWrapper(Comp: types.IBaseRenderer, {
|
||||
return whitelist.includes(schema.componentName);
|
||||
}
|
||||
|
||||
static getDerivedStateFromProps(props: any, state: any) {
|
||||
if (props.__tag === state.__tag) {
|
||||
componentWillReceiveProps(nextProps: any) {
|
||||
if (nextProps.__tag === this.state.__tag) {
|
||||
return null;
|
||||
}
|
||||
const { _leaf, __tag, children, ...rest } = nextProps;
|
||||
if (_leaf && this.leaf && _leaf !== this.leaf) {
|
||||
this.disposeFunctions.forEach(fn => fn());
|
||||
this.disposeFunctions = [];
|
||||
this.initOnChildrenChangeEvent(_leaf);
|
||||
this.initOnPropsChangeEvent(_leaf);
|
||||
this.initOnVisibleChangeEvent(_leaf);
|
||||
}
|
||||
|
||||
return {
|
||||
nodeChildren: props.children,
|
||||
nodeProps: props.nodeProps,
|
||||
this.setState({
|
||||
nodeChildren: children,
|
||||
nodeProps: rest,
|
||||
childrenInState: true,
|
||||
__tag: props.__tag,
|
||||
};
|
||||
__tag,
|
||||
});
|
||||
}
|
||||
|
||||
// static getDerivedStateFromProps(props: any, state: any) {
|
||||
// if (props.__tag === state.__tag) {
|
||||
// return null;
|
||||
// }
|
||||
// if (props._leaf && this.state.leaf && props._leaf !== this.state.leaf) {
|
||||
// this.disposeFunctions.forEach(fn => fn());
|
||||
// }
|
||||
|
||||
// return {
|
||||
// nodeChildren: props.children,
|
||||
// nodeProps: props.nodeProps,
|
||||
// childrenInState: true,
|
||||
// __tag: props.__tag,
|
||||
// _leaf: props._leaf,
|
||||
// };
|
||||
// }
|
||||
|
||||
shouldComponentUpdate() {
|
||||
if (this.isInWhitelist) {
|
||||
__debug(`${schema.componentName} is in leaf Hoc whitelist`);
|
||||
@ -164,12 +188,12 @@ export function leafWrapper(Comp: types.IBaseRenderer, {
|
||||
}
|
||||
|
||||
/** 监听参数变化 */
|
||||
initOnPropsChangeEvent(): void {
|
||||
const dispose = this.leaf?.onPropChange?.((propChangeInfo: PropChangeOptions) => {
|
||||
initOnPropsChangeEvent(leaf = this.leaf): void {
|
||||
const dispose = leaf?.onPropChange?.((propChangeInfo: PropChangeOptions) => {
|
||||
const {
|
||||
key,
|
||||
} = propChangeInfo;
|
||||
const node = this.leaf;
|
||||
const node = leaf;
|
||||
|
||||
// 如果循坏条件变化,从根节点重新渲染
|
||||
// 目前多层循坏无法判断需要从哪一层开始渲染,故先粗暴解决
|
||||
@ -180,7 +204,7 @@ export function leafWrapper(Comp: types.IBaseRenderer, {
|
||||
}
|
||||
|
||||
this.beforeRender(RerenderType.PropsChanged);
|
||||
__debug(`${this.leaf?.componentName} component trigger onPropsChange event`);
|
||||
__debug(`${leaf?.componentName} component trigger onPropsChange event`);
|
||||
const nextProps = getProps(node?.export?.(TransformStage.Render) as types.ISchema, Comp, componentInfo);
|
||||
this.setState(nextProps.children ? {
|
||||
nodeChildren: nextProps.children,
|
||||
@ -196,13 +220,13 @@ export function leafWrapper(Comp: types.IBaseRenderer, {
|
||||
/**
|
||||
* 监听显隐变化
|
||||
*/
|
||||
initOnVisibleChangeEvent() {
|
||||
const dispose = this.leaf?.onVisibleChange?.((flag: boolean) => {
|
||||
initOnVisibleChangeEvent(leaf = this.leaf) {
|
||||
const dispose = leaf?.onVisibleChange?.((flag: boolean) => {
|
||||
if (this.state.visible === flag) {
|
||||
return;
|
||||
}
|
||||
|
||||
__debug(`${this.leaf?.componentName} component trigger onVisibleChange event`);
|
||||
__debug(`${leaf?.componentName} component trigger onVisibleChange event`);
|
||||
this.beforeRender(RerenderType.VisibleChanged);
|
||||
this.setState({
|
||||
visible: flag,
|
||||
@ -215,15 +239,15 @@ export function leafWrapper(Comp: types.IBaseRenderer, {
|
||||
/**
|
||||
* 监听子元素变化(拖拽,删除...)
|
||||
*/
|
||||
initOnChildrenChangeEvent() {
|
||||
const dispose = this.leaf?.onChildrenChange?.((param): void => {
|
||||
initOnChildrenChangeEvent(leaf = this.leaf) {
|
||||
const dispose = leaf?.onChildrenChange?.((param): void => {
|
||||
const {
|
||||
type,
|
||||
node,
|
||||
} = param || {};
|
||||
this.beforeRender(`${RerenderType.ChildChanged}-${type}`, node);
|
||||
__debug(`${this.leaf} component trigger onChildrenChange event`);
|
||||
const nextChild = getChildren(this.leaf?.export?.(TransformStage.Render) as types.ISchema, Comp);
|
||||
__debug(`${leaf} component trigger onChildrenChange event`);
|
||||
const nextChild = getChildren(leaf?.export?.(TransformStage.Render) as types.ISchema, Comp);
|
||||
this.setState({
|
||||
nodeChildren: nextChild,
|
||||
childrenInState: true,
|
||||
@ -238,15 +262,16 @@ export function leafWrapper(Comp: types.IBaseRenderer, {
|
||||
}
|
||||
|
||||
get hasChildren(): boolean {
|
||||
let { children } = this.props;
|
||||
if (this.state.childrenInState) {
|
||||
return !!this.state.nodeChildren?.length;
|
||||
children = this.state.nodeChildren;
|
||||
}
|
||||
|
||||
if (Array.isArray(this.props.children)) {
|
||||
return Boolean(this.props.children && this.props.children.length);
|
||||
if (Array.isArray(children)) {
|
||||
return Boolean(children && children.length);
|
||||
}
|
||||
|
||||
return Boolean(this.props.children);
|
||||
return Boolean(children);
|
||||
}
|
||||
|
||||
get children(): any {
|
||||
@ -305,4 +330,4 @@ export function leafWrapper(Comp: types.IBaseRenderer, {
|
||||
LeafWrapper.displayName = (Comp as any).displayName;
|
||||
|
||||
return LeafWrapper;
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user