写在前面:
-
本文遇到的问题发生在 Vue3 情景下,但 Vue2 也同理的;
-
本文的前两点原因来自这里。因为这篇文章付费,而且嘎嘎贵,我就把大概内容再写一遍。(ps:我已经付过钱了,这个收益不知道能不能到文章作者手里,也不知道这个价格谁定的,真狠啊)
问题来源:
尝试给两个节点添加连线的时候,控制台报了如标题一样的错误
可能原因1: 来源节点和目标节点位置重合
注:上图来源于此,本人非原创
这个很好解决,改改 css 样式,修改一下位置即可
可能原因2: 渲染时机有问题
- 可能是你在渲染连线之前,来源节点和目标节点都没有被渲染出来;
- 可能是你在渲染连线之前,父容器没有被渲染出来,或者父容器宽高为0;
解决的办法如下:
用 nextTick() 或者叠加 setTimeout
this.createNode() // 先渲染节点
this.$nextTick(() => {
// 在这里调用渲染连线的方法
this.echoRelations()
})
// 或者
this.createNode() // 先渲染节点
this.$nextTick(() => {
setTimeout(() => {
// 在这里调用渲染连线的方法
this.echoRelations()
}, 2000) // 秒数看情况, 如果秒数很大的话, 推荐加个 loading 效果
})
// vue3 的代码我就不写了,基本一模一样的
可能原因3: 未调用 jsPlumb 提供的 API 来清空渲染的图
这个也是我真正遇到的问题。
我的需求是:左边是列表,右边是展示的区域,点击列表中的某项后,根据当前项的信息,更新渲染出来的图。
我的操作是:先清空右边的区域,然后再重新渲染。
问题就出在了清空这里,具体代码如下:
const container = document.getElementById('diagramContainer')
container.innerHTML = ''
这样的操作虽然可以清空父容器内的所有DOM元素,但会报标题的错误,并且连线也不会被渲染出来,正确的清空代码应该是这样的:
// 关键是这里,清空 DOM 元素的同时也要调用 jsPlumb 提供的 API,
// 并且我强烈建议你在 vue 的 beforeDestroy 生命周期函数中也调用一次这个 API
jsPlumb.reset()
const container = document.getElementById('diagramContainer')
container.innerHTML = ''
这样就不会报错了,然后再调用渲染的方法即可。