mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2026-01-13 09:41:57 +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)) {
|
||||
return;
|
||||
}
|
||||
this._nodesMap.delete(node.id);
|
||||
node.remove(useMutator);
|
||||
}
|
||||
|
||||
unlinkNode(node: Node) {
|
||||
this.nodes.delete(node);
|
||||
this.selection.remove(node.id);
|
||||
node.remove();
|
||||
this._nodesMap.delete(node.id);
|
||||
}
|
||||
|
||||
@obx.ref private _dropLocation: DropLocation | null = null;
|
||||
@ -318,20 +320,20 @@ export class DocumentModel {
|
||||
* 导出 schema 数据
|
||||
*/
|
||||
get schema(): RootSchema {
|
||||
return this.rootNode.schema as any;
|
||||
return this.rootNode?.schema as any;
|
||||
}
|
||||
|
||||
import(schema: RootSchema, checkId = false) {
|
||||
// TODO: do purge
|
||||
this.nodes.forEach(node => {
|
||||
this.internalRemoveAndPurgeNode(node, true);
|
||||
this.destroyNode(node);
|
||||
});
|
||||
this.rootNode.import(schema as any, checkId);
|
||||
this.rootNode?.import(schema as any, checkId);
|
||||
// todo: select added and active track added
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
@ -56,7 +56,7 @@ export class NodeChildren {
|
||||
}
|
||||
|
||||
this.children = children;
|
||||
this.interalInitParent();
|
||||
this.internalInitParent();
|
||||
if (!shallowEqual(children, originChildren)) {
|
||||
this.emitter.emit('change');
|
||||
}
|
||||
@ -92,20 +92,53 @@ export class NodeChildren {
|
||||
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);
|
||||
if (i < 0) {
|
||||
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) {
|
||||
// should set parent null
|
||||
deleted.internalSetParent(null, useMutator);
|
||||
deleted.purge(useMutator);
|
||||
node.internalSetParent(null, 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');
|
||||
if (useMutator) {
|
||||
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]() {
|
||||
// 保证向前兼容性
|
||||
return 'Array';
|
||||
@ -331,7 +352,7 @@ export class NodeChildren {
|
||||
try {
|
||||
callbacks?.onSubtreeModified.call(node, owner, options);
|
||||
} 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 : '',
|
||||
});
|
||||
} else {
|
||||
// 这里 props 被初始化两次,一次 new,一次 import,new 的实例需要给 propsReducer 的钩子去使用,
|
||||
// import 是为了使用钩子返回的值,并非完全幂等的操作,部分行为执行两次会有 bug,
|
||||
// 所以在 props 里会对 new / import 做一些区别化的解析
|
||||
this.props = new Props(this, props, extras);
|
||||
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.setupAutoruns();
|
||||
}
|
||||
@ -258,14 +261,15 @@ export class Node<Schema extends NodeSchema = NodeSchema> {
|
||||
return;
|
||||
}
|
||||
|
||||
// 解除老的父子关系,但不需要真的删除节点
|
||||
if (this._parent) {
|
||||
if (this.isSlot()) {
|
||||
this._parent.removeSlot(this, false);
|
||||
this._parent.unlinkSlot(this);
|
||||
} else {
|
||||
this._parent.children.delete(this, false, useMutator);
|
||||
this._parent.children.unlinkChild(this);
|
||||
}
|
||||
}
|
||||
|
||||
// 建立新的父子关系
|
||||
this._parent = parent;
|
||||
if (parent) {
|
||||
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.isSlot()) {
|
||||
this.parent.removeSlot(this, true);
|
||||
this.parent.removeSlot(this, purge);
|
||||
} 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);
|
||||
}
|
||||
|
||||
unlinkSlot(slotNode: Node) {
|
||||
const i = this._slots.indexOf(slotNode);
|
||||
if (i < 0) {
|
||||
return false;
|
||||
}
|
||||
this._slots.splice(i, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除一个Slot节点
|
||||
*/
|
||||
@ -653,12 +665,14 @@ export class Node<Schema extends NodeSchema = NodeSchema> {
|
||||
if (i < 0) {
|
||||
return false;
|
||||
}
|
||||
const deleted = this._slots.splice(i, 1)[0];
|
||||
if (purge) {
|
||||
// should set parent null
|
||||
deleted.internalSetParent(null);
|
||||
deleted.purge();
|
||||
slotNode.internalSetParent(null, false);
|
||||
slotNode.purge();
|
||||
}
|
||||
this.document.unlinkNode(slotNode);
|
||||
this.document.selection.remove(slotNode.id);
|
||||
this._slots.splice(i, 1);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -699,20 +713,10 @@ export class Node<Schema extends NodeSchema = NodeSchema> {
|
||||
if (this.purged) {
|
||||
return;
|
||||
}
|
||||
// if (this._parent) {
|
||||
// // should remove thisNode before purge
|
||||
// this.remove(useMutator);
|
||||
// return;
|
||||
// }
|
||||
this.purged = true;
|
||||
if (this.isParental()) {
|
||||
this.children.purge(useMutator);
|
||||
}
|
||||
this.autoruns?.forEach((dispose) => dispose());
|
||||
this.props.purge();
|
||||
this.document.internalRemoveAndPurgeNode(this);
|
||||
this.document.destroyNode(this);
|
||||
this.remove(useMutator);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -22,6 +22,37 @@ export class Prop implements IPropParent {
|
||||
readonly isProp = true;
|
||||
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
|
||||
*/
|
||||
@ -197,7 +228,7 @@ export class Prop implements IPropParent {
|
||||
} else if (Array.isArray(val)) {
|
||||
this._type = 'list';
|
||||
} else if (isPlainObject(val)) {
|
||||
if (isJSSlot(val)) {
|
||||
if (isJSSlot(val) && this.options.propsMode !== 'init') {
|
||||
this.setAsSlot(val);
|
||||
return;
|
||||
}
|
||||
@ -347,34 +378,6 @@ export class Prop implements IPropParent {
|
||||
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 如果不存在,临时获取一个待写入
|
||||
|
||||
@ -57,9 +57,9 @@ export class Props implements IPropParent {
|
||||
constructor(readonly owner: Node, value?: PropsMap | PropsList | null, extras?: object) {
|
||||
if (Array.isArray(value)) {
|
||||
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) {
|
||||
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) {
|
||||
Object.keys(extras).forEach(key => {
|
||||
|
||||
@ -26,21 +26,10 @@ export const designer = new Designer({ editor: editor });
|
||||
editor.set(Designer, designer);
|
||||
editor.set('designer', designer);
|
||||
|
||||
let nodeCache: any = {};
|
||||
designer.project.onCurrentDocumentChange((doc) => {
|
||||
nodeCache = {};
|
||||
doc.nodesMap.forEach((node) => {
|
||||
nodeCache[node.id] = node;
|
||||
});
|
||||
doc.onRendererReady(() => {
|
||||
bus.emit(VE_EVENTS.VE_PAGE_PAGE_READY);
|
||||
});
|
||||
doc.onNodeCreate((node) => {
|
||||
nodeCache[node.id] = node;
|
||||
});
|
||||
doc.onNodeDestroy((node) => {
|
||||
delete nodeCache[node.id];
|
||||
});
|
||||
});
|
||||
|
||||
interface Variable {
|
||||
@ -89,6 +78,18 @@ function upgradePropsReducer(props: any) {
|
||||
// 升级 Props
|
||||
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 初始化
|
||||
designer.addPropsReducer((props, node) => {
|
||||
// run initials
|
||||
@ -96,16 +97,8 @@ designer.addPropsReducer((props, node) => {
|
||||
...props,
|
||||
};
|
||||
if (newProps.fieldId) {
|
||||
const fieldIds: any = [];
|
||||
Object.keys(nodeCache).forEach(nodeId => {
|
||||
if (nodeId === node.id) {
|
||||
return;
|
||||
}
|
||||
const fieldId = nodeCache[nodeId].getPropValue('fieldId');
|
||||
if (fieldId) {
|
||||
fieldIds.push(fieldId);
|
||||
}
|
||||
});
|
||||
const fieldIds = getCurrentFieldIds();
|
||||
|
||||
// 全局的关闭 uniqueIdChecker 信号,在 ve-utils 中实现
|
||||
if (fieldIds.indexOf(props.fieldId) >= 0 && !(window as any).__disable_unique_id_checker__) {
|
||||
newProps.fieldId = undefined;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user