@logicflow/vue-node-registry
Version:
LogicFlow Vue Component Node Registry
121 lines • 4.7 kB
JavaScript
import { defineComponent, h, createApp, reactive, isVue3, Teleport, markRaw, Fragment, } from 'vue-demi';
var active = false;
var appInstances = new Map();
var appNodesMap = new Map(); // 用于储存当前流程图节点id当节点都销毁时同时卸载vueApp实例
var items = reactive({});
export function connect(id, component, container, node, graph) {
if (active) {
if (graph.isMiniMap) {
createTeleportContainer(container, graph.flowId);
}
items[id] = markRaw(defineComponent({
render: function () {
return h(Teleport, { to: container }, [
h(component, { node: node, graph: graph }),
]);
},
provide: function () { return ({
getNode: function () { return node; },
getGraph: function () { return graph; },
}); },
}));
}
}
export function disconnect(id, flowId) {
if (active) {
delete items[id];
if (appInstances.has(flowId)) {
var appNodeList = appNodesMap.get(flowId) || [];
var index = appNodeList.indexOf(id);
if (index > -1) {
appNodeList.splice(index, 1);
if (appNodeList.length === 0) {
destroyTeleportContainer(flowId);
}
else {
appNodesMap.set(flowId, appNodeList);
}
}
}
}
}
export function isActive() {
return active;
}
export function getTeleport() {
if (!isVue3) {
throw new Error('teleport is only available in Vue3');
}
active = true;
return defineComponent({
props: {
flowId: {
type: String,
required: true,
},
},
setup: function (props) {
return function () {
var children = [];
Object.keys(items).forEach(function (id) {
// https://github.com/didi/LogicFlow/issues/1768
// 多个不同的VueNodeView都会connect注册到items中,因此items存储了可能有多个flowId流程图的数据
// 当使用多个LogicFlow时,会创建多个flowId + 同时使用KeepAlive
// 每一次items改变,会触发不同flowId持有的setup()执行,由于每次setup()执行就是遍历items,因此存在多次重复渲染元素的问题
// 即items[0]会在Page1的setup()执行,items[0]也会在Page2的setup()执行,从而生成两个items[0]
// 比对当前界面显示的flowId,只更新items[当前页面flowId:nodeId]的数据
// 比如items[0]属于Page1的数据,那么Page2无论active=true/false,都无法执行items[0]
if (id.startsWith(props.flowId)) {
if (appInstances.has(props.flowId)) {
var appNodeList = appNodesMap.get(props.flowId) || [];
if (!appNodeList.includes(id)) {
appNodeList.push(id);
appNodesMap.set(props.flowId, appNodeList);
}
}
children.push(items[id]);
}
});
return h(Fragment, {}, children.map(function (item) { return h(item); }));
};
},
});
}
/**
* 创建并挂载 Teleport 容器组件
* @param container 目标容器元素
* @param flowId 当前流程图的唯一标识
*/
export function createTeleportContainer(container, flowId) {
if (!isVue3 || !flowId || !container || !active)
return;
// 获取 Teleport 组件
var TeleportContainer = getTeleport();
// 不重新创建 Teleport 容器组件
if (appInstances.has(flowId)) {
return;
}
// ✅ 1. 创建独立容器放到目标容器中
var mountPoint = document.createElement('div');
container.appendChild(mountPoint);
// ✅ 2. 创建并挂载 Vue 应用到新容器
var app = createApp(TeleportContainer, { flowId: flowId });
app.mount(mountPoint);
appInstances.set(flowId, app);
appNodesMap.set(flowId, []);
}
/**
* 卸载 Teleport 容器组件
* @param flowId 需要卸载流程图的唯一标识
*/
export function destroyTeleportContainer(flowId) {
if (!isVue3 || !flowId || !active)
return;
var app = appInstances.get(flowId);
if (app) {
app.unmount();
appInstances.delete(flowId);
appNodesMap.delete(flowId);
}
}
//# sourceMappingURL=teleport.js.map