本 篇 文 档只讲解vue3中 如何 使用 ,vue2的 可 以参考 下 官 方 文 档
@antv/x6-vue-shape
既 然 使用 vue节点,那 么我们就需要 准 备一个vue的 组件,这个组件就是节点的 一 些样式 ,根 据 你们的 ui自 行 写 代 码即可
<template>
<div>节点名称 </div>
<div>节点描 述 </div>
……
</template>
- 导入vue节点
注 册 插件
import { register, getTeleport } from '@antv/x6-vue-shape';
注 册 节点
register({
shape: 'custom-vue-node',
width: 'auto',
height: 104,
component: vueNode // 这个就是你定义的vue组件
});
添加 传送门
import { getTeleport } from '@antv/x6-vue-shape';
const TeleportContainer = defineComponent(getTeleport());
// template 中 添加 标签,和 你的画布 容器 平 级
<div id="graphDom"></div>
<TeleportContainer />
使用
const node = graph.createNode({
shape: 'custom-vue-node',
width: 100,
height: 104,
label: data?.name,
id: data?.id,
// 所有 节点的 数 据 源 头都在 这里设置,需要 哪些字 段 自 行 添加 即 可
data: {
name: data?.name, // 节点的 名称
img: data?.img || remoteImgUrl.value, // 图标
desc: data?.dataNum || 0, // 总数据 描述
……
},
/**
* 连接桩位置 判断 逻辑
* 1、数 据 源 类型的 连接桩只显示右 侧
* 2、算 子 类型的 连接桩显示 左右 两侧
* 3、算 子 类型-关联回 填 的 连接桩显示 左 侧
*/
ports: {
...port
}
});
const getNodeData = inject('getNode');
onMounted(() => {
const currentNode = getNodeData();
// 监听当 前 节点数 据 发生了 变化
currentNode.on('change:data', ({ current }) => {
console.log('节点数 据 是 否 发生变化了 >>>', current);
});
})
<template>
<div>内容 :{{ dataNode.name }}</div>
<n-badge>
<n-avatar :src="vueIco"></n-avatar>
</n-badge>
</template>
<div>
<div>内容 :{{ dataNode.name }}</div>
<n-badge>
<n-avatar :src="vueIco"></n-avatar>
</n-badge>
</div>
因 为我用 的 是 vue类型的 节点,所以 这里就按照 vue节点来 进行讲解,其它的 节点(React、Angular、Html)这些都 是 通用 的 。
在 vue节点内部 的 某 个元素 上 需要 执行一 个点击事件 ,但 是 在 执行本 事件 的 时候不能 去 触 发node:click
的 事件 、在 执行node:click
事件 的 时候不能 触 发vue节点的 点 击事件 ,也就是 两边的 事件 都 是 独立 的 ,谁也不能 影 响谁,而且vue节点内的 点 击事件 在 点 击的时候还得获取当 前 节点信 息
stop
node:click
// vue节点的 事件
@click.stop = test
// 父 页面的 节点节点事件
graph.on('node:click',{e} => {
e.stopPropagation()
})
node:click
graph.on('node:click',{e} => {
// 判断 target的 className或 者 id,或 者 你定义的一些自定义属性,
// 反 正 只 要 你能知道 当 前 点 击的区域 是 属 于谁的 就行
// 我 在 vue节点点 击事件 的 标签上 加 了 个class
if(e.target.className == 'cu-class') return
})
vue节点
这个
方案 属 于野路子 ,不 是 很灵活 ,如果不 是 复选框 那 基本 凉凉了
// vue节点内 正常 写 复选框 绑定的 逻辑
const checked2 = ref(false);
<el-checkbox v-model="checked2" size="large" @change="checkChange"></el-checkbox>
// 父 组件监听节点的 点 击事件
graph.on('node:click',({e,node}) => {
let state = node.data.checkState ?? false;
// 这个判断 是 为了解 决复选框的 点 击事件 和 节点的 点 击事件 冲突的 问题
if (e.target.className == 'el-checkbox__inner') {
// 给节点 添加 一 个checkState属性 ,标识是 否 选中
node.updateData({ checkState: !state }, { ignoreHistory: true });
return;
}
})
// 最 后 点 击保存 按钮的 时候获取下 节点checkState为true的 数 据
const save = () => {
const allNodes = graph.getNodes();
// 我 这里是 取的 id属性 ,如果你们需要 其它的 可 以自行 组装
checkedOps.value = allNodes.filter(item => item.data.checkState).map(item => item.id);
console.log('checkedOps >>>', checkedOps.value);
}
这个
方案 就可以随便 玩了,不 再 局限 于我自己 的 需求,如果还要在 节点上 加 其它的 控 件 都 可 以完美的 把 数 据 传递到父 组件,其灵感 来 源 于github的 小 伙伴qw123gz,问官方 交流 群 的 群 主 ,问了半天 也没有 给出方案 ……
<el-checkbox v-model="checked2" size="large" @change="checkChange"></el-checkbox>
const checked2 = ref(false);
const emits = defineEmits(['getCheckVal']);
const checkChange = val => {
emits('getCheckVal', val);
};
register({
shape: 'custom-vue-node',
width: 'auto',
height: 104,
// component: vueNode 这个是 官 方 提供 的 注 册 方式
component: {
// 使用 vue3的 render渲染组件,并添加 自 定 义事件
render() {
return h(vueNode, {
// 事件 名称 前面 必须添加 `on`
onGetCheckVal: val => getMyCheckVal(val)
});
}
}
});
今 天 在 封 装画 布 节点预览组件的 时候,发现从这个组件 跳 转到编辑页面的 时候,节点重 复渲染 了 ,也就是 原 来 有 两个节点,现在变成了 4个节点 ,原本 以为是 我 本地 缓存,但 是 刷新 页面也还是 会 重 复渲染 ……,那 这就有 点 摸不着 头脑了 ,于是开始去 社 区 找小伙伴们的帮助,确定了 问题的 根源 在 于TeleportContainer
,最 后 社 区 的 小 伙伴也是给了个下面 的 解 决方案
TeleportContainer
,TeleportContainer
// 父 页面A
route.push('/fb?delTeleport=true');
// 父 页面B
<TeleportContainer v-if="!delTeleport"/>
推荐TeleportContainer
,App.vue
<template>
<TeleportContainer />
</template>
import { getTeleport } from '@antv/x6-vue-shape';
// x6的 vue节点数 据 传送门
const TeleportContainer = defineComponent(getTeleport());