mirror of
https://github.com/Tencent/tmagic-editor.git
synced 2026-03-23 22:12:26 +00:00
refactor(dep): 优化性能
This commit is contained in:
parent
a34d0cdccc
commit
1664559d8f
@ -71,7 +71,7 @@ export default class Target {
|
|||||||
|
|
||||||
this.deps[id] = dep;
|
this.deps[id] = dep;
|
||||||
|
|
||||||
if (dep.keys.indexOf(key) === -1) {
|
if (!dep.keys.includes(key)) {
|
||||||
dep.keys.push(key);
|
dep.keys.push(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -115,7 +115,7 @@ export default class Target {
|
|||||||
public hasDep(id: string | number, key: string | number) {
|
public hasDep(id: string | number, key: string | number) {
|
||||||
const dep = this.deps[id];
|
const dep = this.deps[id];
|
||||||
|
|
||||||
return Boolean(dep?.keys.find((d) => d === key));
|
return dep?.keys.includes(key) ?? false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public destroy() {
|
public destroy() {
|
||||||
|
|||||||
@ -5,6 +5,12 @@ import type Target from './Target';
|
|||||||
import { type DepExtendedData, DepTargetType, type TargetList, TargetNode } from './types';
|
import { type DepExtendedData, DepTargetType, type TargetList, TargetNode } from './types';
|
||||||
import { traverseTarget } from './utils';
|
import { traverseTarget } from './utils';
|
||||||
|
|
||||||
|
const DATA_SOURCE_TARGET_TYPES: Set<string> = new Set([
|
||||||
|
DepTargetType.DATA_SOURCE,
|
||||||
|
DepTargetType.DATA_SOURCE_COND,
|
||||||
|
DepTargetType.DATA_SOURCE_METHOD,
|
||||||
|
]);
|
||||||
|
|
||||||
export default class Watcher {
|
export default class Watcher {
|
||||||
private targetsList: TargetList = {};
|
private targetsList: TargetList = {};
|
||||||
private childrenProp = 'items';
|
private childrenProp = 'items';
|
||||||
@ -159,7 +165,7 @@ export default class Watcher {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const clearedItemsNodeIds: (string | number)[] = [];
|
const clearedItemsNodeIds = new Set<string | number>();
|
||||||
traverseTarget(targetsList, (target) => {
|
traverseTarget(targetsList, (target) => {
|
||||||
if (nodes) {
|
if (nodes) {
|
||||||
for (const node of nodes) {
|
for (const node of nodes) {
|
||||||
@ -168,9 +174,9 @@ export default class Watcher {
|
|||||||
if (
|
if (
|
||||||
Array.isArray(node[this.childrenProp]) &&
|
Array.isArray(node[this.childrenProp]) &&
|
||||||
node[this.childrenProp].length &&
|
node[this.childrenProp].length &&
|
||||||
!clearedItemsNodeIds.includes(node[this.idProp])
|
!clearedItemsNodeIds.has(node[this.idProp])
|
||||||
) {
|
) {
|
||||||
clearedItemsNodeIds.push(node[this.idProp]);
|
clearedItemsNodeIds.add(node[this.idProp]);
|
||||||
this.clear(node[this.childrenProp]);
|
this.clear(node[this.childrenProp]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -190,12 +196,7 @@ export default class Watcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public collectItem(node: TargetNode, target: Target, depExtendedData: DepExtendedData = {}, deep = false) {
|
public collectItem(node: TargetNode, target: Target, depExtendedData: DepExtendedData = {}, deep = false) {
|
||||||
const dataSourceTargetTypes: string[] = [
|
if (node[NODE_DISABLE_DATA_SOURCE_KEY] && DATA_SOURCE_TARGET_TYPES.has(target.type)) {
|
||||||
DepTargetType.DATA_SOURCE,
|
|
||||||
DepTargetType.DATA_SOURCE_COND,
|
|
||||||
DepTargetType.DATA_SOURCE_METHOD,
|
|
||||||
];
|
|
||||||
if (node[NODE_DISABLE_DATA_SOURCE_KEY] && dataSourceTargetTypes.includes(target.type)) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -18,6 +18,8 @@ import {
|
|||||||
import Target from './Target';
|
import Target from './Target';
|
||||||
import { DepTargetType, type TargetList } from './types';
|
import { DepTargetType, type TargetList } from './types';
|
||||||
|
|
||||||
|
const INTEGER_REGEXP = /^\d+$/;
|
||||||
|
|
||||||
export const createCodeBlockTarget = (id: Id, codeBlock: CodeBlockContent, initialDeps: DepData = {}) =>
|
export const createCodeBlockTarget = (id: Id, codeBlock: CodeBlockContent, initialDeps: DepData = {}) =>
|
||||||
new Target({
|
new Target({
|
||||||
type: DepTargetType.CODE_BLOCK,
|
type: DepTargetType.CODE_BLOCK,
|
||||||
@ -30,8 +32,7 @@ export const createCodeBlockTarget = (id: Id, codeBlock: CodeBlockContent, initi
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (value?.hookType === HookType.CODE && Array.isArray(value.hookData)) {
|
if (value?.hookType === HookType.CODE && Array.isArray(value.hookData)) {
|
||||||
const index = value.hookData.findIndex((item: HookData) => item.codeId === id);
|
return value.hookData.some((item: HookData) => item.codeId === id);
|
||||||
return Boolean(index > -1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@ -54,12 +55,7 @@ export const isIncludeArrayField = (keys: string[], fields: DataSchema[]) => {
|
|||||||
f = field?.fields || [];
|
f = field?.fields || [];
|
||||||
|
|
||||||
// 字段类型为数组并且后面没有数字索引
|
// 字段类型为数组并且后面没有数字索引
|
||||||
return (
|
return field?.type === 'array' && index < keys.length - 1 && !INTEGER_REGEXP.test(keys[index + 1]);
|
||||||
field?.type === 'array' &&
|
|
||||||
// 不是整数
|
|
||||||
/^(?!\d+$).*$/.test(`${keys[index + 1]}`) &&
|
|
||||||
index < keys.length - 1
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -78,33 +74,25 @@ export const isDataSourceTemplate = (value: any, ds: Pick<DataSourceSchema, 'id'
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const arrayFieldTemplates = [];
|
for (const tpl of templates) {
|
||||||
const fieldTemplates = [];
|
|
||||||
|
|
||||||
templates.forEach((tpl) => {
|
|
||||||
// 将${dsId.xxxx} 转成 dsId.xxxx
|
// 将${dsId.xxxx} 转成 dsId.xxxx
|
||||||
const expression = tpl.substring(2, tpl.length - 1);
|
const expression = tpl.substring(2, tpl.length - 1);
|
||||||
const keys = getKeysArray(expression);
|
const keys = getKeysArray(expression);
|
||||||
const dsId = keys.shift();
|
const dsId = keys.shift();
|
||||||
|
|
||||||
if (!dsId || dsId !== ds.id) {
|
if (!dsId || dsId !== ds.id) {
|
||||||
return;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ${dsId.array} ${dsId.array[0]} ${dsId.array[0].a} 这种是依赖
|
// ${dsId.array} ${dsId.array[0]} ${dsId.array[0].a} 这种是依赖
|
||||||
// ${dsId.array.a} 这种不是依赖,这种需要再迭代器容器中的组件才能使用,依赖由迭代器处理
|
// ${dsId.array.a} 这种不是依赖,这种需要再迭代器容器中的组件才能使用,依赖由迭代器处理
|
||||||
if (isIncludeArrayField(keys, ds.fields)) {
|
const includesArray = isIncludeArrayField(keys, ds.fields);
|
||||||
arrayFieldTemplates.push(tpl);
|
if (hasArray === includesArray) {
|
||||||
} else {
|
return true;
|
||||||
fieldTemplates.push(tpl);
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
if (hasArray) {
|
|
||||||
return arrayFieldTemplates.length > 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return fieldTemplates.length > 0;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -184,7 +172,12 @@ export const isDataSourceTarget = (
|
|||||||
value: any,
|
value: any,
|
||||||
hasArray = false,
|
hasArray = false,
|
||||||
) => {
|
) => {
|
||||||
if (!value || !['string', 'object'].includes(typeof value)) {
|
if (!value) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const valueType = typeof value;
|
||||||
|
if (valueType !== 'string' && valueType !== 'object') {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -193,13 +186,13 @@ export const isDataSourceTarget = (
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 或者在模板在使用数据源
|
// 或者在模板在使用数据源
|
||||||
if (typeof value === 'string') {
|
if (valueType === 'string') {
|
||||||
return isDataSourceTemplate(value, ds, hasArray);
|
return isDataSourceTemplate(value, ds, hasArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 关联数据源对象,如:{ isBindDataSource: true, dataSourceId: 'xxx'}
|
// 关联数据源对象,如:{ isBindDataSource: true, dataSourceId: 'xxx'}
|
||||||
// 使用data-source-select value: 'value' 可以配置出来
|
// 使用data-source-select value: 'value' 可以配置出来
|
||||||
if (isObject(value) && value?.isBindDataSource && value.dataSourceId && value.dataSourceId === ds.id) {
|
if (isObject(value) && value.isBindDataSource && value.dataSourceId === ds.id) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,10 +203,7 @@ export const isDataSourceTarget = (
|
|||||||
if (isUseDataSourceField(value, ds.id)) {
|
if (isUseDataSourceField(value, ds.id)) {
|
||||||
const [, ...keys] = value;
|
const [, ...keys] = value;
|
||||||
const includeArray = isIncludeArrayField(keys, ds.fields);
|
const includeArray = isIncludeArrayField(keys, ds.fields);
|
||||||
if (hasArray) {
|
return hasArray ? includeArray : !includeArray;
|
||||||
return includeArray;
|
|
||||||
}
|
|
||||||
return !includeArray;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@ -235,12 +225,9 @@ export const isDataSourceCondTarget = (
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ds.fields?.find((field) => field.name === keys[0])) {
|
if (ds.fields?.some((field) => field.name === keys[0])) {
|
||||||
const includeArray = isIncludeArrayField(keys, ds.fields);
|
const includeArray = isIncludeArrayField(keys, ds.fields);
|
||||||
if (hasArray) {
|
return hasArray ? includeArray : !includeArray;
|
||||||
return includeArray;
|
|
||||||
}
|
|
||||||
return !includeArray;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@ -282,12 +269,12 @@ export const createDataSourceMethodTarget = (
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ds.methods?.find((method) => method.name === methodName)) {
|
if (ds.methods?.some((method) => method.name === methodName)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 配置的方法名称可能会是数据源类中定义的,并不存在于methods中,所以这里判断如果methodName如果是字段名称,就表示配置的不是方法
|
// 配置的方法名称可能会是数据源类中定义的,并不存在于methods中,所以这里判断如果methodName如果是字段名称,就表示配置的不是方法
|
||||||
if (ds.fields?.find((field) => field.name === methodName)) {
|
if (ds.fields?.some((field) => field.name === methodName)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -300,11 +287,18 @@ export const traverseTarget = (
|
|||||||
cb: (target: Target) => void,
|
cb: (target: Target) => void,
|
||||||
type?: DepTargetType | string,
|
type?: DepTargetType | string,
|
||||||
) => {
|
) => {
|
||||||
|
if (type) {
|
||||||
|
const targets = targetsList[type];
|
||||||
|
if (targets) {
|
||||||
|
for (const target of Object.values(targets)) {
|
||||||
|
cb(target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (const targets of Object.values(targetsList)) {
|
for (const targets of Object.values(targetsList)) {
|
||||||
for (const target of Object.values(targets)) {
|
for (const target of Object.values(targets)) {
|
||||||
if (type && target.type !== type) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
cb(target);
|
cb(target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user