mirror of
https://github.com/Tencent/tmagic-editor.git
synced 2025-04-06 03:57:56 +08:00
fix: 调整绑定关系结构,优化性能
This commit is contained in:
parent
6637fdc92b
commit
a013f35cd9
@ -362,6 +362,8 @@ export default defineComponent({
|
||||
disabledDragStart: props.disabledDragStart,
|
||||
}),
|
||||
);
|
||||
// 监听组件update
|
||||
codeBlockService.addCodeRelationListener();
|
||||
|
||||
return services;
|
||||
},
|
||||
|
@ -6,7 +6,12 @@
|
||||
type="card"
|
||||
tab-position="left"
|
||||
>
|
||||
<component :is="uiComponent.component" v-for="(config, index) in sideBarItems" :key="index" :name="config.text">
|
||||
<component
|
||||
:is="uiComponent.component"
|
||||
v-for="(config, index) in sideBarItems"
|
||||
:key="config.$key || index"
|
||||
:name="config.text"
|
||||
>
|
||||
<template #label>
|
||||
<div :key="config.text">
|
||||
<MIcon v-if="config.icon" :icon="config.icon"></MIcon>
|
||||
|
@ -87,7 +87,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="MEditorCodeBlockList">
|
||||
import { computed, inject, reactive, ref, watch } from 'vue';
|
||||
import { computed, inject, onMounted, reactive, ref, watch } from 'vue';
|
||||
import { Close, Edit, Link, View } from '@element-plus/icons-vue';
|
||||
import { cloneDeep, forIn, isEmpty } from 'lodash-es';
|
||||
|
||||
@ -96,7 +96,7 @@ import { ColumnConfig } from '@tmagic/form';
|
||||
import { CodeBlockContent, Id } from '@tmagic/schema';
|
||||
|
||||
import Icon from '../../../components/Icon.vue';
|
||||
import type { CodeRelation, Services } from '../../../type';
|
||||
import type { CodeRelation, CombineInfo, Services } from '../../../type';
|
||||
import { CodeDeleteErrorType, CodeDslItem, ListState } from '../../../type';
|
||||
|
||||
import codeBlockEditor from './CodeBlockEditor.vue';
|
||||
@ -121,17 +121,22 @@ const isShowCodeBlockEditor = computed(() => services?.codeBlockService.getCodeE
|
||||
const codeCombineInfo = ref<CodeRelation | null>(null);
|
||||
|
||||
// 根据代码块ID获取其绑定的组件信息
|
||||
const getBindCompsByCodeId = (codeId: Id) => {
|
||||
if (!codeCombineInfo.value || !codeCombineInfo.value[codeId]) return [];
|
||||
const bindCompsId = Object.keys(codeCombineInfo.value[codeId]);
|
||||
return bindCompsId.map((compId) => ({
|
||||
compId,
|
||||
compName: getCompName(compId),
|
||||
}));
|
||||
const getBindCompsByCodeId = (codeId: Id): CombineInfo[] => {
|
||||
if (!codeCombineInfo.value) return [];
|
||||
const bindsComp = [] as CombineInfo[];
|
||||
forIn(codeCombineInfo.value, (codeIds, compId) => {
|
||||
if (codeIds.includes(codeId)) {
|
||||
bindsComp.push({
|
||||
compId,
|
||||
compName: getCompName(compId),
|
||||
});
|
||||
}
|
||||
});
|
||||
return bindsComp as CombineInfo[];
|
||||
};
|
||||
|
||||
// 初始化代码块列表
|
||||
const initList = async () => {
|
||||
// 更新代码块列表
|
||||
const refreshCodeList = async () => {
|
||||
const codeDsl = cloneDeep(await services?.codeBlockService.getCodeDsl()) || null;
|
||||
codeCombineInfo.value = cloneDeep(services?.codeBlockService.getCombineInfo()) || null;
|
||||
if (!codeDsl || !codeCombineInfo.value) return;
|
||||
@ -147,13 +152,17 @@ const initList = async () => {
|
||||
});
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
services?.codeBlockService.refreshAllRelations();
|
||||
refreshCodeList();
|
||||
});
|
||||
|
||||
watch(
|
||||
[() => services?.codeBlockService.getCodeDslSync(), () => services?.codeBlockService.refreshCombineInfo()],
|
||||
[() => services?.codeBlockService.getCodeDslSync(), () => services?.codeBlockService.getCombineInfo()],
|
||||
() => {
|
||||
initList();
|
||||
refreshCodeList();
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
deep: true,
|
||||
},
|
||||
);
|
||||
|
@ -17,7 +17,7 @@
|
||||
*/
|
||||
|
||||
import { reactive } from 'vue';
|
||||
import { cloneDeep, forIn, isEmpty, keys, omit, pick } from 'lodash-es';
|
||||
import { cloneDeep, forIn, isEmpty, keys, omit, pick, union } from 'lodash-es';
|
||||
|
||||
import { CodeBlockContent, CodeBlockDSL, HookType, Id, MNode } from '@tmagic/schema';
|
||||
|
||||
@ -230,16 +230,39 @@ class CodeBlock extends BaseService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新绑定关系
|
||||
* @returns {CodeRelation | null}
|
||||
* 监听组件更新来更新代码块绑定关系
|
||||
* @returns {void}
|
||||
*/
|
||||
public refreshCombineInfo(): CodeRelation | null {
|
||||
public addCodeRelationListener(): void {
|
||||
// 监听组件更新
|
||||
editorService.on('update', (nodes: MNode[]) => {
|
||||
const relations: CodeRelation = cloneDeep(this.state.relations);
|
||||
nodes.forEach((node: MNode) => {
|
||||
if (node?.id) {
|
||||
relations[node.id] = [];
|
||||
this.getNodeRelation(node, relations);
|
||||
}
|
||||
});
|
||||
this.state.relations = { ...relations };
|
||||
});
|
||||
// 监听组件删除
|
||||
editorService.on('remove', (nodes: MNode[]) => {
|
||||
nodes.forEach((node: MNode) => {
|
||||
this.state.relations = this.deleteNodeRelation(node, this.state.relations);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新全部绑定关系
|
||||
* @returns {void}
|
||||
*/
|
||||
public refreshAllRelations(): void {
|
||||
const root = editorService.get('root');
|
||||
if (!root) return null;
|
||||
const relations = {};
|
||||
this.recurseMNode(root, relations);
|
||||
if (!root) return;
|
||||
const relations: CodeRelation = {};
|
||||
this.getNodeRelation(root, relations, true);
|
||||
this.state.relations = relations;
|
||||
return this.state.relations;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -313,18 +336,6 @@ class CodeBlock extends BaseService {
|
||||
return await this.getUniqueId();
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过组件id解除绑定关系(删除组件)
|
||||
* @param {MNode} compId 组件节点
|
||||
* @returns void
|
||||
*/
|
||||
public async deleteCompsInRelation(node: MNode): Promise<void> {
|
||||
const codeDsl = cloneDeep(await this.getCodeDsl());
|
||||
if (!codeDsl) return;
|
||||
this.refreshRelationDeep(node, codeDsl);
|
||||
this.setCodeDsl(codeDsl);
|
||||
}
|
||||
|
||||
public resetState() {
|
||||
this.state.isShowCodeEditor = false;
|
||||
this.state.codeDsl = null;
|
||||
@ -340,63 +351,63 @@ class CodeBlock extends BaseService {
|
||||
this.removeAllPlugins();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除组件时 如果是容器 需要遍历删除其包含节点的绑定信息
|
||||
* @param {MNode} node 节点信息
|
||||
* @param {CodeBlockDSL} codeDsl 代码块
|
||||
* @returns void
|
||||
*/
|
||||
private refreshRelationDeep(node: MNode, codeDsl: CodeBlockDSL): void {
|
||||
if (!node.id) return;
|
||||
forIn(codeDsl, (codeBlockContent) => {
|
||||
const compsContent = codeBlockContent.comps || {};
|
||||
codeBlockContent.comps = omit(compsContent, node.id);
|
||||
});
|
||||
if (!isEmpty(node.items)) {
|
||||
node.items.forEach((item: MNode) => {
|
||||
this.refreshRelationDeep(item, codeDsl);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归遍历dsl中挂载了代码块的节点,并更新绑定关系数据
|
||||
* @param {MContainer} node 节点信息
|
||||
* @param {MNode} node 节点信息
|
||||
* @param {CodeRelation} relation 关系数据
|
||||
* @param {boolean} deep 是否深层遍历
|
||||
* @returns void
|
||||
*/
|
||||
private recurseMNode(node: MNode, relations: CodeRelation): void {
|
||||
private getNodeRelation(node: MNode, relation: CodeRelation, deep = false): void {
|
||||
forIn(node, (value, key) => {
|
||||
let unConfirmedValue: MNode = { id: node.id };
|
||||
if (value?.hookType === HookType.CODE && !isEmpty(value.hookData)) {
|
||||
value.hookData.forEach((relationItem: HookData) => {
|
||||
// continue
|
||||
if (!relationItem.codeId) return;
|
||||
if (!relations[relationItem.codeId]) {
|
||||
relations[relationItem.codeId] = {};
|
||||
if (relationItem.codeId) {
|
||||
relation[node.id] = union(relation[node.id], [relationItem.codeId]);
|
||||
}
|
||||
const codeItem = relations[relationItem.codeId];
|
||||
if (isEmpty(codeItem[node.id])) {
|
||||
codeItem[node.id] = [];
|
||||
}
|
||||
codeItem[node.id].push(key);
|
||||
});
|
||||
// continue
|
||||
return;
|
||||
}
|
||||
if (typeof value === 'object') {
|
||||
let isContinue = false;
|
||||
try {
|
||||
// 只遍历更新当前组件的关系,不再深层遍历容器包含的组件
|
||||
isContinue = key !== 'items' && typeof value === 'object' && JSON.stringify(value).includes('hookType');
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
if (isContinue) {
|
||||
// 检查value内部是否有嵌套
|
||||
unConfirmedValue = {
|
||||
...unConfirmedValue,
|
||||
const unConfirmedValue = {
|
||||
id: node.id,
|
||||
...value,
|
||||
};
|
||||
this.recurseMNode(unConfirmedValue, relations);
|
||||
this.getNodeRelation(unConfirmedValue, relation);
|
||||
}
|
||||
// 深层遍历用于代码列表初始化
|
||||
if (key === 'items' && !isEmpty(value) && deep) {
|
||||
value.forEach((item: MNode) => {
|
||||
this.getNodeRelation(item, relation, deep);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除组件关系
|
||||
* @param {MNode} node 节点信息
|
||||
* @param {CodeRelation} relations 关系数据
|
||||
* @returns CodeRelation
|
||||
*/
|
||||
private deleteNodeRelation(node: MNode, relations: CodeRelation): CodeRelation {
|
||||
if (!node.id) return {};
|
||||
let newRelations = omit(relations, [node.id]);
|
||||
if (!isEmpty(node.items)) {
|
||||
node.items.forEach((item: MNode) => {
|
||||
this.recurseMNode(item, relations);
|
||||
newRelations = this.deleteNodeRelation(item, newRelations);
|
||||
});
|
||||
}
|
||||
return newRelations;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,6 @@ import { NodeType } from '@tmagic/schema';
|
||||
import StageCore from '@tmagic/stage';
|
||||
import { getNodePath, isNumber, isPage, isPop } from '@tmagic/utils';
|
||||
|
||||
import codeBlockService from '../services/codeBlock';
|
||||
import historyService from '../services/history';
|
||||
import storageService, { Protocol } from '../services/storage';
|
||||
import type { AddMNode, EditorNodeInfo, PastePosition, StepValue, StoreState, StoreStateKey } from '../type';
|
||||
@ -452,9 +451,6 @@ class Editor extends BaseService {
|
||||
}
|
||||
|
||||
this.addModifiedNodeId(parent.id);
|
||||
|
||||
// 通知codeBlockService解除绑定关系
|
||||
codeBlockService.deleteCompsInRelation(node);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -555,7 +551,6 @@ class Editor extends BaseService {
|
||||
this.pushHistoryState();
|
||||
|
||||
this.emit('update', newNodes);
|
||||
codeBlockService.refreshCombineInfo();
|
||||
return Array.isArray(config) ? newNodes : newNodes[0];
|
||||
}
|
||||
|
||||
|
@ -351,10 +351,8 @@ export type HookData = {
|
||||
};
|
||||
|
||||
export type CodeRelation = {
|
||||
[codeId: Id]: {
|
||||
/** 组件id:['created'] */
|
||||
[compId: Id]: string[];
|
||||
};
|
||||
/** 组件id:[代码id1,代码id2] */
|
||||
[compId: Id]: Id[];
|
||||
};
|
||||
|
||||
export interface CodeDslItem {
|
||||
|
Loading…
x
Reference in New Issue
Block a user