mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2026-01-15 10:48:17 +00:00
Merge branch 'fix/lihao-bugs-200902' into 'release/0.9.17'
refactor: 重新梳理 purge / remove / delete 的职责,以及相应重构 refactor: 调整判断 fieldId 是否存在的逻辑 fix: 解决 redo 时页面节点数不对以及 fieldId 被重置 See merge request !960745
This commit is contained in:
commit
67f34ea3b4
@ -267,14 +267,16 @@ export class DocumentModel {
|
|||||||
/**
|
/**
|
||||||
* 内部方法,请勿调用
|
* 内部方法,请勿调用
|
||||||
*/
|
*/
|
||||||
internalRemoveAndPurgeNode(node: Node) {
|
internalRemoveAndPurgeNode(node: Node, useMutator = false) {
|
||||||
if (!this.nodes.has(node)) {
|
if (!this.nodes.has(node)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this._nodesMap.delete(node.id);
|
node.remove(useMutator);
|
||||||
|
}
|
||||||
|
|
||||||
|
unlinkNode(node: Node) {
|
||||||
this.nodes.delete(node);
|
this.nodes.delete(node);
|
||||||
this.selection.remove(node.id);
|
this._nodesMap.delete(node.id);
|
||||||
node.remove();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@obx.ref private _dropLocation: DropLocation | null = null;
|
@obx.ref private _dropLocation: DropLocation | null = null;
|
||||||
@ -318,20 +320,20 @@ export class DocumentModel {
|
|||||||
* 导出 schema 数据
|
* 导出 schema 数据
|
||||||
*/
|
*/
|
||||||
get schema(): RootSchema {
|
get schema(): RootSchema {
|
||||||
return this.rootNode.schema as any;
|
return this.rootNode?.schema as any;
|
||||||
}
|
}
|
||||||
|
|
||||||
import(schema: RootSchema, checkId = false) {
|
import(schema: RootSchema, checkId = false) {
|
||||||
// TODO: do purge
|
|
||||||
this.nodes.forEach(node => {
|
this.nodes.forEach(node => {
|
||||||
|
this.internalRemoveAndPurgeNode(node, true);
|
||||||
this.destroyNode(node);
|
this.destroyNode(node);
|
||||||
});
|
});
|
||||||
this.rootNode.import(schema as any, checkId);
|
this.rootNode?.import(schema as any, checkId);
|
||||||
// todo: select added and active track added
|
// todo: select added and active track added
|
||||||
}
|
}
|
||||||
|
|
||||||
export(stage: TransformStage = TransformStage.Serilize) {
|
export(stage: TransformStage = TransformStage.Serilize) {
|
||||||
return this.rootNode.export(stage);
|
return this.rootNode?.export(stage);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -16,7 +16,7 @@ export class NodeChildren {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interalInitParent() {
|
internalInitParent() {
|
||||||
this.children.forEach(child => child.internalSetParent(this.owner));
|
this.children.forEach(child => child.internalSetParent(this.owner));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,7 +56,7 @@ export class NodeChildren {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.children = children;
|
this.children = children;
|
||||||
this.interalInitParent();
|
this.internalInitParent();
|
||||||
if (!shallowEqual(children, originChildren)) {
|
if (!shallowEqual(children, originChildren)) {
|
||||||
this.emitter.emit('change');
|
this.emitter.emit('change');
|
||||||
}
|
}
|
||||||
@ -92,20 +92,53 @@ export class NodeChildren {
|
|||||||
return this.children.length;
|
return this.children.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private purged = false;
|
||||||
/**
|
/**
|
||||||
* 删除一个节点
|
* 回收销毁
|
||||||
*/
|
*/
|
||||||
delete(node: Node, purge = false, useMutator = true): boolean {
|
purge(useMutator = true) {
|
||||||
|
if (this.purged) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.purged = true;
|
||||||
|
this.children.forEach((child) => {
|
||||||
|
child.purge(useMutator);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
unlinkChild(node: Node) {
|
||||||
const i = this.children.indexOf(node);
|
const i = this.children.indexOf(node);
|
||||||
if (i < 0) {
|
if (i < 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const deleted = this.children.splice(i, 1)[0];
|
this.children.splice(i, 1);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 删除一个节点
|
||||||
|
*/
|
||||||
|
delete(node: Node, purge = false, useMutator = true): boolean {
|
||||||
|
if (node.isParental()) {
|
||||||
|
node.children.forEach(subNode => {
|
||||||
|
subNode.remove(useMutator, purge);
|
||||||
|
});
|
||||||
|
}
|
||||||
if (purge) {
|
if (purge) {
|
||||||
// should set parent null
|
// should set parent null
|
||||||
deleted.internalSetParent(null, useMutator);
|
node.internalSetParent(null, useMutator);
|
||||||
deleted.purge(useMutator);
|
try {
|
||||||
|
node.purge(useMutator);
|
||||||
|
} catch(err) {
|
||||||
|
console.error(err);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
const i = this.children.indexOf(node);
|
||||||
|
if (i < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this.children.splice(i, 1);
|
||||||
|
const document = node.document;
|
||||||
|
document.unlinkNode(node);
|
||||||
|
document.selection.remove(node.id);
|
||||||
this.emitter.emit('change');
|
this.emitter.emit('change');
|
||||||
if (useMutator) {
|
if (useMutator) {
|
||||||
this.reportModified(node, this.owner, {type: 'remove', removeIndex: i, removeNode: node});
|
this.reportModified(node, this.owner, {type: 'remove', removeIndex: i, removeNode: node});
|
||||||
@ -294,18 +327,6 @@ export class NodeChildren {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private purged = false;
|
|
||||||
/**
|
|
||||||
* 回收销毁
|
|
||||||
*/
|
|
||||||
purge(useMutator = true) {
|
|
||||||
if (this.purged) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.purged = true;
|
|
||||||
this.children.forEach((child) => child.purge(useMutator));
|
|
||||||
}
|
|
||||||
|
|
||||||
get [Symbol.toStringTag]() {
|
get [Symbol.toStringTag]() {
|
||||||
// 保证向前兼容性
|
// 保证向前兼容性
|
||||||
return 'Array';
|
return 'Array';
|
||||||
@ -331,7 +352,7 @@ export class NodeChildren {
|
|||||||
try {
|
try {
|
||||||
callbacks?.onSubtreeModified.call(node, owner, options);
|
callbacks?.onSubtreeModified.call(node, owner, options);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('error when excute experimental.callbacks.onNodeAdd', e);
|
console.error('error when excute experimental.callbacks.onSubtreeModified', e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -155,9 +155,12 @@ export class Node<Schema extends NodeSchema = NodeSchema> {
|
|||||||
children: isDOMText(children) || isJSExpression(children) ? children : '',
|
children: isDOMText(children) || isJSExpression(children) ? children : '',
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
// 这里 props 被初始化两次,一次 new,一次 import,new 的实例需要给 propsReducer 的钩子去使用,
|
||||||
|
// import 是为了使用钩子返回的值,并非完全幂等的操作,部分行为执行两次会有 bug,
|
||||||
|
// 所以在 props 里会对 new / import 做一些区别化的解析
|
||||||
this.props = new Props(this, props, extras);
|
this.props = new Props(this, props, extras);
|
||||||
this._children = new NodeChildren(this as ParentalNode, this.initialChildren(children));
|
this._children = new NodeChildren(this as ParentalNode, this.initialChildren(children));
|
||||||
this._children.interalInitParent();
|
this._children.internalInitParent();
|
||||||
this.props.import(this.upgradeProps(this.initProps(props || {})), this.upgradeProps(extras || {}));
|
this.props.import(this.upgradeProps(this.initProps(props || {})), this.upgradeProps(extras || {}));
|
||||||
this.setupAutoruns();
|
this.setupAutoruns();
|
||||||
}
|
}
|
||||||
@ -258,14 +261,15 @@ export class Node<Schema extends NodeSchema = NodeSchema> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 解除老的父子关系,但不需要真的删除节点
|
||||||
if (this._parent) {
|
if (this._parent) {
|
||||||
if (this.isSlot()) {
|
if (this.isSlot()) {
|
||||||
this._parent.removeSlot(this, false);
|
this._parent.unlinkSlot(this);
|
||||||
} else {
|
} else {
|
||||||
this._parent.children.delete(this, false, useMutator);
|
this._parent.children.unlinkChild(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 建立新的父子关系
|
||||||
this._parent = parent;
|
this._parent = parent;
|
||||||
if (parent) {
|
if (parent) {
|
||||||
this.document.removeWillPurge(this);
|
this.document.removeWillPurge(this);
|
||||||
@ -298,12 +302,12 @@ export class Node<Schema extends NodeSchema = NodeSchema> {
|
|||||||
/**
|
/**
|
||||||
* 移除当前节点
|
* 移除当前节点
|
||||||
*/
|
*/
|
||||||
remove(useMutator = true) {
|
remove(useMutator = true, purge = true) {
|
||||||
if (this.parent) {
|
if (this.parent) {
|
||||||
if (this.isSlot()) {
|
if (this.isSlot()) {
|
||||||
this.parent.removeSlot(this, true);
|
this.parent.removeSlot(this, purge);
|
||||||
} else {
|
} else {
|
||||||
this.parent.children.delete(this, true, useMutator);
|
this.parent.children.delete(this, purge, useMutator);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -645,6 +649,14 @@ export class Node<Schema extends NodeSchema = NodeSchema> {
|
|||||||
return comparePosition(this, otherNode);
|
return comparePosition(this, otherNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unlinkSlot(slotNode: Node) {
|
||||||
|
const i = this._slots.indexOf(slotNode);
|
||||||
|
if (i < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this._slots.splice(i, 1);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除一个Slot节点
|
* 删除一个Slot节点
|
||||||
*/
|
*/
|
||||||
@ -653,12 +665,14 @@ export class Node<Schema extends NodeSchema = NodeSchema> {
|
|||||||
if (i < 0) {
|
if (i < 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const deleted = this._slots.splice(i, 1)[0];
|
|
||||||
if (purge) {
|
if (purge) {
|
||||||
// should set parent null
|
// should set parent null
|
||||||
deleted.internalSetParent(null);
|
slotNode.internalSetParent(null, false);
|
||||||
deleted.purge();
|
slotNode.purge();
|
||||||
}
|
}
|
||||||
|
this.document.unlinkNode(slotNode);
|
||||||
|
this.document.selection.remove(slotNode.id);
|
||||||
|
this._slots.splice(i, 1);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -699,20 +713,10 @@ export class Node<Schema extends NodeSchema = NodeSchema> {
|
|||||||
if (this.purged) {
|
if (this.purged) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// if (this._parent) {
|
|
||||||
// // should remove thisNode before purge
|
|
||||||
// this.remove(useMutator);
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
this.purged = true;
|
this.purged = true;
|
||||||
if (this.isParental()) {
|
|
||||||
this.children.purge(useMutator);
|
|
||||||
}
|
|
||||||
this.autoruns?.forEach((dispose) => dispose());
|
this.autoruns?.forEach((dispose) => dispose());
|
||||||
this.props.purge();
|
this.props.purge();
|
||||||
this.document.internalRemoveAndPurgeNode(this);
|
|
||||||
this.document.destroyNode(this);
|
this.document.destroyNode(this);
|
||||||
this.remove(useMutator);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -22,6 +22,37 @@ export class Prop implements IPropParent {
|
|||||||
readonly isProp = true;
|
readonly isProp = true;
|
||||||
readonly owner: Node;
|
readonly owner: Node;
|
||||||
|
|
||||||
|
private stash: PropStash | undefined;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 键值
|
||||||
|
*/
|
||||||
|
@obx key: string | number | undefined;
|
||||||
|
/**
|
||||||
|
* 扩展值
|
||||||
|
*/
|
||||||
|
@obx spread: boolean;
|
||||||
|
|
||||||
|
readonly props: Props;
|
||||||
|
readonly options: any;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
public parent: IPropParent,
|
||||||
|
value: CompositeValue | UNSET = UNSET,
|
||||||
|
key?: string | number,
|
||||||
|
spread = false,
|
||||||
|
options = {},
|
||||||
|
) {
|
||||||
|
this.owner = parent.owner;
|
||||||
|
this.props = parent.props;
|
||||||
|
this.key = key;
|
||||||
|
this.spread = spread;
|
||||||
|
this.options = options;
|
||||||
|
if (value !== UNSET) {
|
||||||
|
this.setValue(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see SettingTarget
|
* @see SettingTarget
|
||||||
*/
|
*/
|
||||||
@ -197,7 +228,7 @@ export class Prop implements IPropParent {
|
|||||||
} else if (Array.isArray(val)) {
|
} else if (Array.isArray(val)) {
|
||||||
this._type = 'list';
|
this._type = 'list';
|
||||||
} else if (isPlainObject(val)) {
|
} else if (isPlainObject(val)) {
|
||||||
if (isJSSlot(val)) {
|
if (isJSSlot(val) && this.options.propsMode !== 'init') {
|
||||||
this.setAsSlot(val);
|
this.setAsSlot(val);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -347,34 +378,6 @@ export class Prop implements IPropParent {
|
|||||||
return this._maps;
|
return this._maps;
|
||||||
}
|
}
|
||||||
|
|
||||||
private stash: PropStash | undefined;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 键值
|
|
||||||
*/
|
|
||||||
@obx key: string | number | undefined;
|
|
||||||
/**
|
|
||||||
* 扩展值
|
|
||||||
*/
|
|
||||||
@obx spread: boolean;
|
|
||||||
|
|
||||||
readonly props: Props;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
public parent: IPropParent,
|
|
||||||
value: CompositeValue | UNSET = UNSET,
|
|
||||||
key?: string | number,
|
|
||||||
spread = false,
|
|
||||||
) {
|
|
||||||
this.owner = parent.owner;
|
|
||||||
this.props = parent.props;
|
|
||||||
if (value !== UNSET) {
|
|
||||||
this.setValue(value);
|
|
||||||
}
|
|
||||||
this.key = key;
|
|
||||||
this.spread = spread;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取某个属性
|
* 获取某个属性
|
||||||
* @param stash 如果不存在,临时获取一个待写入
|
* @param stash 如果不存在,临时获取一个待写入
|
||||||
|
|||||||
@ -57,9 +57,9 @@ export class Props implements IPropParent {
|
|||||||
constructor(readonly owner: Node, value?: PropsMap | PropsList | null, extras?: object) {
|
constructor(readonly owner: Node, value?: PropsMap | PropsList | null, extras?: object) {
|
||||||
if (Array.isArray(value)) {
|
if (Array.isArray(value)) {
|
||||||
this.type = 'list';
|
this.type = 'list';
|
||||||
this.items = value.map(item => new Prop(this, item.value, item.name, item.spread));
|
this.items = value.map(item => new Prop(this, item.value, item.name, item.spread, { propsMode: 'init' }));
|
||||||
} else if (value != null) {
|
} else if (value != null) {
|
||||||
this.items = Object.keys(value).map(key => new Prop(this, value[key], key));
|
this.items = Object.keys(value).map(key => new Prop(this, value[key], key, false, { propsMode: 'init' }));
|
||||||
}
|
}
|
||||||
if (extras) {
|
if (extras) {
|
||||||
Object.keys(extras).forEach(key => {
|
Object.keys(extras).forEach(key => {
|
||||||
|
|||||||
@ -26,21 +26,10 @@ export const designer = new Designer({ editor: editor });
|
|||||||
editor.set(Designer, designer);
|
editor.set(Designer, designer);
|
||||||
editor.set('designer', designer);
|
editor.set('designer', designer);
|
||||||
|
|
||||||
let nodeCache: any = {};
|
|
||||||
designer.project.onCurrentDocumentChange((doc) => {
|
designer.project.onCurrentDocumentChange((doc) => {
|
||||||
nodeCache = {};
|
|
||||||
doc.nodesMap.forEach((node) => {
|
|
||||||
nodeCache[node.id] = node;
|
|
||||||
});
|
|
||||||
doc.onRendererReady(() => {
|
doc.onRendererReady(() => {
|
||||||
bus.emit(VE_EVENTS.VE_PAGE_PAGE_READY);
|
bus.emit(VE_EVENTS.VE_PAGE_PAGE_READY);
|
||||||
});
|
});
|
||||||
doc.onNodeCreate((node) => {
|
|
||||||
nodeCache[node.id] = node;
|
|
||||||
});
|
|
||||||
doc.onNodeDestroy((node) => {
|
|
||||||
delete nodeCache[node.id];
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
interface Variable {
|
interface Variable {
|
||||||
@ -89,6 +78,18 @@ function upgradePropsReducer(props: any) {
|
|||||||
// 升级 Props
|
// 升级 Props
|
||||||
designer.addPropsReducer(upgradePropsReducer, TransformStage.Upgrade);
|
designer.addPropsReducer(upgradePropsReducer, TransformStage.Upgrade);
|
||||||
|
|
||||||
|
function getCurrentFieldIds() {
|
||||||
|
const fieldIds: any = [];
|
||||||
|
const nodesMap = designer?.currentDocument?.nodesMap || new Map();
|
||||||
|
nodesMap.forEach((curNode: any) => {
|
||||||
|
const fieldId = nodesMap?.get(curNode.id)?.getPropValue('fieldId');
|
||||||
|
if (fieldId) {
|
||||||
|
fieldIds.push(fieldId);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return fieldIds;
|
||||||
|
}
|
||||||
|
|
||||||
// 节点 props 初始化
|
// 节点 props 初始化
|
||||||
designer.addPropsReducer((props, node) => {
|
designer.addPropsReducer((props, node) => {
|
||||||
// run initials
|
// run initials
|
||||||
@ -96,16 +97,8 @@ designer.addPropsReducer((props, node) => {
|
|||||||
...props,
|
...props,
|
||||||
};
|
};
|
||||||
if (newProps.fieldId) {
|
if (newProps.fieldId) {
|
||||||
const fieldIds: any = [];
|
const fieldIds = getCurrentFieldIds();
|
||||||
Object.keys(nodeCache).forEach(nodeId => {
|
|
||||||
if (nodeId === node.id) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const fieldId = nodeCache[nodeId].getPropValue('fieldId');
|
|
||||||
if (fieldId) {
|
|
||||||
fieldIds.push(fieldId);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// 全局的关闭 uniqueIdChecker 信号,在 ve-utils 中实现
|
// 全局的关闭 uniqueIdChecker 信号,在 ve-utils 中实现
|
||||||
if (fieldIds.indexOf(props.fieldId) >= 0 && !(window as any).__disable_unique_id_checker__) {
|
if (fieldIds.indexOf(props.fieldId) >= 0 && !(window as any).__disable_unique_id_checker__) {
|
||||||
newProps.fieldId = undefined;
|
newProps.fieldId = undefined;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user