refactor: 优化初始创建 doc 时触发响应式获取 schema 的次数

This commit is contained in:
lihao.ylh 2021-09-17 20:48:01 +08:00
parent f4e07fe290
commit 3b645d270d
9 changed files with 172 additions and 17 deletions

View File

@ -6,7 +6,7 @@ module.exports = {
// // '^.+\\.(ts|tsx)$': 'ts-jest',
// // '^.+\\.(js|jsx)$': 'babel-jest',
// },
// testMatch: ['**/prop.test.ts'],
// testMatch: ['**/builtin-hotkey.test.ts'],
// testMatch: ['(/tests?/.*(test))\\.[jt]s$'],
transformIgnorePatterns: [
`/node_modules/(?!${esModules})/`,

View File

@ -1,5 +1,5 @@
import { EventEmitter } from 'events';
import { autorun, Reaction, untracked, globalContext, Editor } from '@ali/lowcode-editor-core';
import { autorun, reaction, mobx, untracked, globalContext, Editor } from '@ali/lowcode-editor-core';
import { NodeSchema } from '@ali/lowcode-types';
// TODO: cache to localStorage
@ -37,17 +37,12 @@ export class History {
this.session = new Session(0, null, this.timeGap);
this.records = [this.session];
autorun(() => {
reaction(() => {
return logger();
}, (data) => {
if (this.asleep) return;
const data = logger();
untracked(() => {
const log = currentSerialization.serialize(data);
if (this.session.cursor === 0 && this.session.isActive()) {
// first log
this.session.log(log);
this.session.end();
} else if (this.session) {
if (this.session.isActive()) {
this.session.log(log);
} else {
@ -62,9 +57,9 @@ export class History {
this.emitter.emit('statechange', currentState);
}
}
}
// }
});
});
}, { fireImmediately: true });
}
get hotData() {

View File

@ -122,7 +122,7 @@ export class ModalNodesManager {
}
private setNodes() {
const nodes = getModalNodes(this.page.getRoot());
const nodes = getModalNodes(this.page.getRoot()!);
this.modalNodes = nodes;
this.modalNodes.forEach((node: Node) => {
this.addNodeEvent(node);

View File

@ -179,6 +179,8 @@ export class Node<Schema extends NodeSchema = NodeSchema> {
this.setupAutoruns();
}
this.initBuiltinProps();
this.isInited = true;
this.emitter = new EventEmitter();
}
@ -191,6 +193,18 @@ export class Node<Schema extends NodeSchema = NodeSchema> {
return this._settingEntry;
}
/**
* prop reaction
*/
private initBuiltinProps() {
this.props.has(getConvertedExtraKey('hidden')) || this.props.add(false, getConvertedExtraKey('hidden'));
this.props.has(getConvertedExtraKey('title')) || this.props.add('', getConvertedExtraKey('title'));
this.props.has(getConvertedExtraKey('isLocked')) || this.props.add(false, getConvertedExtraKey('isLocked'));
this.props.has(getConvertedExtraKey('condition')) || this.props.add(true, getConvertedExtraKey('condition'));
this.props.has(getConvertedExtraKey('conditionGroup')) || this.props.add('', getConvertedExtraKey('conditionGroup'));
this.props.has(getConvertedExtraKey('loop')) || this.props.add(undefined, getConvertedExtraKey('loop'));
}
private initProps(props: any): any {
return this.document.designer.transformProps(props, this, TransformStage.Init);
}

View File

@ -102,6 +102,9 @@ describe('快捷键测试', () => {
const firstButtonNode = designer.currentDocument?.getNode('node_k1ow3cbn')!;
let secondButtonNode = designer.currentDocument?.getNode('node_k1ow3cbp')!;
// 等待第一个 session 结束
await new Promise(resolve => setTimeout(resolve, 1000));
firstButtonNode.remove();
expect(secondButtonNode.getParent()?.children.size).toBe(1);
@ -119,6 +122,9 @@ describe('快捷键测试', () => {
const firstButtonNode = designer.currentDocument?.getNode('node_k1ow3cbn')!;
let secondButtonNode = designer.currentDocument?.getNode('node_k1ow3cbp')!;
// 等待第一个 session 结束
await new Promise(resolve => setTimeout(resolve, 1000));
firstButtonNode.remove();
expect(secondButtonNode.getParent()?.children.size).toBe(1);

View File

@ -68,7 +68,11 @@ Object {
Object {
"componentName": "PageHeader",
"condition": true,
"conditionGroup": "",
"hidden": false,
"id": "node_k1ow3cbd",
"isLocked": false,
"loop": undefined,
"props": Object {
"__slot__action": false,
"__slot__content": false,
@ -108,12 +112,18 @@ Object {
],
},
},
"title": "",
},
],
"componentName": "RootHeader",
"condition": true,
"conditionGroup": "",
"hidden": false,
"id": "node_k1ow3cba",
"isLocked": false,
"loop": undefined,
"props": Object {},
"title": "",
},
Object {
"children": Array [
@ -130,7 +140,11 @@ Object {
Object {
"componentName": "TextField",
"condition": true,
"conditionGroup": "",
"hidden": false,
"id": "node_k1ow3cbz",
"isLocked": false,
"loop": undefined,
"props": Object {
"__category__": "form",
"__style__": Object {},
@ -200,11 +214,16 @@ Object {
"wrapperColOffset": 0,
"wrapperColSpan": 0,
},
"title": "",
},
Object {
"componentName": "TextField",
"condition": true,
"conditionGroup": "",
"hidden": false,
"id": "node_k1ow3cc1",
"isLocked": false,
"loop": undefined,
"props": Object {
"__category__": "form",
"__style__": Object {},
@ -270,11 +289,16 @@ Object {
"wrapperColOffset": 0,
"wrapperColSpan": 0,
},
"title": "",
},
Object {
"componentName": "TextField",
"condition": true,
"conditionGroup": "",
"hidden": false,
"id": "node_k1ow3cc3",
"isLocked": false,
"loop": undefined,
"props": Object {
"__category__": "form",
"__style__": Object {},
@ -340,23 +364,33 @@ Object {
"wrapperColOffset": 0,
"wrapperColSpan": 0,
},
"title": "",
},
],
"componentName": "Column",
"condition": true,
"conditionGroup": "",
"hidden": false,
"id": "node_k1ow3cbx",
"isLocked": false,
"loop": undefined,
"props": Object {
"__style__": Object {},
"colSpan": "",
"fieldId": "column_k1p1bnjm",
},
"title": "",
},
Object {
"children": Array [
Object {
"componentName": "TextField",
"condition": true,
"conditionGroup": "",
"hidden": false,
"id": "node_k1ow3cc2",
"isLocked": false,
"loop": undefined,
"props": Object {
"__category__": "form",
"__style__": Object {},
@ -422,11 +456,16 @@ Object {
"wrapperColOffset": 0,
"wrapperColSpan": 0,
},
"title": "",
},
Object {
"componentName": "SelectField",
"condition": true,
"conditionGroup": "",
"hidden": false,
"id": "node_k1ow3cc0",
"isLocked": false,
"loop": undefined,
"props": Object {
"__category__": "form",
"__style__": Object {},
@ -512,21 +551,31 @@ Object {
"wrapperColOffset": 0,
"wrapperColSpan": 0,
},
"title": "",
},
],
"componentName": "Column",
"condition": true,
"conditionGroup": "",
"hidden": false,
"id": "node_k1ow3cby",
"isLocked": false,
"loop": undefined,
"props": Object {
"__style__": Object {},
"colSpan": "",
"fieldId": "column_k1p1bnjn",
},
"title": "",
},
],
"componentName": "ColumnsLayout",
"condition": true,
"conditionGroup": "",
"hidden": false,
"id": "node_k1ow3cbw",
"isLocked": false,
"loop": undefined,
"props": Object {
"__style__": Object {},
"columnGap": "20",
@ -534,17 +583,27 @@ Object {
"layout": "6:6",
"rowGap": 0,
},
"title": "",
},
],
"componentName": "CardContent",
"condition": true,
"conditionGroup": "",
"hidden": false,
"id": "node_k1ow3cbk",
"isLocked": false,
"loop": undefined,
"props": Object {},
"title": "",
},
],
"componentName": "Card",
"condition": true,
"conditionGroup": "",
"hidden": false,
"id": "node_k1ow3cbj",
"isLocked": false,
"loop": undefined,
"props": Object {
"__slot__extra": false,
"__slot__subTitle": false,
@ -576,6 +635,7 @@ Object {
"zh_CN": "基本信息",
},
},
"title": "",
},
Object {
"children": Array [
@ -584,7 +644,11 @@ Object {
Object {
"componentName": "TextField",
"condition": true,
"conditionGroup": "",
"hidden": false,
"id": "node_k1ow3cc4",
"isLocked": false,
"loop": undefined,
"props": Object {
"__category__": "form",
"__style__": Object {},
@ -650,6 +714,7 @@ Object {
"wrapperColOffset": 0,
"wrapperColSpan": 0,
},
"title": "",
},
Object {
"children": Array [
@ -658,7 +723,11 @@ Object {
Object {
"componentName": "TextField",
"condition": true,
"conditionGroup": "",
"hidden": false,
"id": "node_k1ow3cc8",
"isLocked": false,
"loop": undefined,
"props": Object {
"__category__": "form",
"__style__": Object {},
@ -724,23 +793,33 @@ Object {
"wrapperColOffset": 0,
"wrapperColSpan": 0,
},
"title": "",
},
],
"componentName": "Column",
"condition": true,
"conditionGroup": "",
"hidden": false,
"id": "node_k1ow3cc6",
"isLocked": false,
"loop": undefined,
"props": Object {
"__style__": Object {},
"colSpan": "",
"fieldId": "column_k1p1bnjo",
},
"title": "",
},
Object {
"children": Array [
Object {
"componentName": "TextField",
"condition": true,
"conditionGroup": "",
"hidden": false,
"id": "node_k1ow3cc9",
"isLocked": false,
"loop": undefined,
"props": Object {
"__category__": "form",
"__style__": Object {},
@ -806,21 +885,31 @@ Object {
"wrapperColOffset": 0,
"wrapperColSpan": 0,
},
"title": "",
},
],
"componentName": "Column",
"condition": true,
"conditionGroup": "",
"hidden": false,
"id": "node_k1ow3cc7",
"isLocked": false,
"loop": undefined,
"props": Object {
"__style__": Object {},
"colSpan": "",
"fieldId": "column_k1p1bnjp",
},
"title": "",
},
],
"componentName": "ColumnsLayout",
"condition": true,
"conditionGroup": "",
"hidden": false,
"id": "node_k1ow3cc5",
"isLocked": false,
"loop": undefined,
"props": Object {
"__style__": Object {},
"columnGap": "20",
@ -828,17 +917,27 @@ Object {
"layout": "6:6",
"rowGap": 0,
},
"title": "",
},
],
"componentName": "CardContent",
"condition": true,
"conditionGroup": "",
"hidden": false,
"id": "node_k1ow3cbm",
"isLocked": false,
"loop": undefined,
"props": Object {},
"title": "",
},
],
"componentName": "Card",
"condition": true,
"conditionGroup": "",
"hidden": false,
"id": "node_k1ow3cbl",
"isLocked": false,
"loop": undefined,
"props": Object {
"__slot__extra": false,
"__slot__subTitle": false,
@ -870,13 +969,18 @@ Object {
"zh_CN": "部门信息",
},
},
"title": "",
},
Object {
"children": Array [
Object {
"componentName": "Button",
"condition": true,
"conditionGroup": "",
"hidden": false,
"id": "node_k1ow3cbn",
"isLocked": false,
"loop": undefined,
"props": Object {
"__style__": ":root {
margin-right: 16px;
@ -912,11 +1016,16 @@ Object {
"triggerEventsWhenLoading": false,
"type": "primary",
},
"title": "",
},
Object {
"componentName": "Button",
"condition": true,
"conditionGroup": "",
"hidden": false,
"id": "node_k1ow3cbp",
"isLocked": false,
"loop": undefined,
"props": Object {
"__style__": ":root {
width: 80px;
@ -945,11 +1054,16 @@ Object {
"triggerEventsWhenLoading": false,
"type": "normal",
},
"title": "",
},
],
"componentName": "Div",
"condition": true,
"conditionGroup": "",
"hidden": false,
"id": "node_k1ow3cbo",
"isLocked": false,
"loop": undefined,
"props": Object {
"__style__": ":root {
display: flex;
@ -965,12 +1079,17 @@ Object {
"fieldId": "div_k1ow3h1o",
"useFieldIdAsDomId": false,
},
"title": "",
},
],
"componentName": "Form",
"condition": true,
"conditionGroup": "",
"extraPropA": "extraPropA",
"hidden": false,
"id": "form",
"isLocked": false,
"loop": undefined,
"props": Object {
"__style__": Object {},
"autoUnmount": true,
@ -992,26 +1111,38 @@ Object {
"size": "medium",
"slotA": "",
},
"title": "",
},
],
"componentName": "RootContent",
"condition": true,
"conditionGroup": "",
"hidden": false,
"id": "node_k1ow3cbb",
"isLocked": false,
"loop": undefined,
"props": Object {
"contentBgColor": "transparent",
"contentMargin": "20",
"contentPadding": "0",
},
"title": "",
},
Object {
"componentName": "RootFooter",
"condition": true,
"conditionGroup": "",
"hidden": false,
"id": "node_k1ow3cbc",
"isLocked": false,
"loop": undefined,
"props": Object {},
"title": "",
},
],
"componentName": "Page",
"condition": true,
"conditionGroup": "",
"css": "body{background-color:#f2f3f5}.card_kgaqfbm5 {
margin-bottom: 12px;
}.card_kgaqfbm6 {
@ -1042,7 +1173,9 @@ Object {
"online": Array [],
"sync": true,
},
"hidden": false,
"id": "page",
"isLocked": false,
"lifeCycles": Object {
"constructor": Object {
"compiled": "function constructor() {
@ -1070,6 +1203,7 @@ Object.keys(module.exports).forEach(function(item) {
"type": "js",
},
},
"loop": undefined,
"methods": Object {
"__initMethods__": Object {
"compiled": "function (exports, module) { /*set actions code here*/ }",

View File

@ -32,6 +32,12 @@ describe('document-model 测试', () => {
expect(doc.isBlank()).toBeFalsy();
expect(doc.schema).toEqual({
componentName: 'Page',
condition: true,
conditionGroup: '',
hidden: false,
isLocked: false,
loop: undefined,
title: '',
id: 'root',
fileName: '',
props: {},

View File

@ -249,7 +249,7 @@ describe('Node 方法测试', () => {
// getComponentName
btnParent.insertAfter({ getComponentName: () => 'Button' }, firstBtn);
expect(btnParent.children.get(1)?.getProps().export().props).toBeUndefined();
expect(btnParent.children.get(1)?.getProps().export().props).toEqual({});
expect(mockFn).toHaveBeenCalledTimes(3);
});
});

View File

@ -71,14 +71,14 @@ const pages = Object.assign(project, {
componentsTree,
id: pages[0].id,
config: project.config,
},
},
true,
);
// FIXME: 根本原因是 PropStash 导致的在页面节点初始化结束后hideModalNodes 导致了第一次变化
// FIXME: 在页面节点初始化结束后,还有响应式变量变化导致了多次变化
// 这样可以避免页面加载之后就被标记为 isModified
setTimeout(() => {
project.currentDocument?.history.savePoint();
}, 0);
}, 1000);
},
addPage(data: OldPageData | RootSchema) {
if (isPageDataV1(data)) {