在 Vue 的帮助下,块从对象中循环显示。对不起,这个例子很长,但我不知道如何简化以重现问题。
var blocks1 = [{
id: "b1",
pos: [20, 100],
routes: [{
id: "r1",
target: "b2"
}, {
id: "r2",
target: "b3"
}]
},
{
id: "b2",
pos: [130, 50]
},
{
id: "b3",
pos: [130, 150]
}
];
var blocks2 = [{
id: "b4",
pos: [25, 110]
},
{
id: "b5",
pos: [120, 60],
routes: [{
id: "r3",
target: "b4"
}, {
id: "r4",
target: "b6"
}]
},
{
id: "b6",
pos: [135, 140]
}
];
var jsp = jsPlumb.getInstance({
Container: "jsp",
Anchors: ["Right", "Left"]
});
var app = new Vue({
el: "#app",
data: {
blocks: blocks1
},
mounted: function() {
console.clear();
console.log("vue mounted");
drawLines();
makeDraggable();
},
updated: function() {
console.log("vue changed");
drawLines(); //рисуем связи заново
//makeDraggable(); почему работает без этого?
},
methods: {
changeData: function() {
jsp.reset(); //сбрасываем jsplumb
this.blocks = blocks2; //меняем данные
}
}
});
function makeDraggable() {
let blocks = document.querySelectorAll(".block");
for (var block of blocks) {
jsp.draggable(block.id);
}
}
function drawLines() { //перебираем маршруты
let routes = document.querySelectorAll(".route");
for (var route of routes) {
drawLine(route);
}
}
function drawLine(route) { //рисуем связь
jsp.connect({
source: route.id,
target: route.dataset.target
});
}
.block {
position: absolute;
padding: 1rem;
background-color: #eee;
}
.jtk-endpoint {
display: none;
}
<div id="jsp">
<div id="app">
<button @click="changeData">change data</button>
<div class="block" v-for="block in blocks" :id="block.id" :style="{top:block.pos[1]+'px', left:block.pos[0]+'px'}">
<div class="title">{{block.id}}</div>
<div class="routes">
<div class="route" v-for="route in block.routes" :data-target="route.target" :id="route.id">
{{route.target}}
</div>
</div>
</div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jsPlumb/2.11.2/js/jsplumb.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js"></script>
有 jsPlumb,它在将 DOM 渲染到 hook 之后mounted()
,使这些块可拖动并在它们之间绘制链接。到目前为止一切顺利,一切正常。
现在我想加载另一个框图并更改对象。我用方法重置jsPlumb reset()
,Vue重绘新块,jsPlumb重绘链接,但是当用传出链接拖动b5块时,一切都中断了。
在日志中给出:
jsPlumb 函数失败:TypeError:无法读取未定义的属性“el”
如何解决?
还有一个问题,为什么新绘制的方块会变成可拖动的?看来 Vue 并没有完全擦除它们,而是改变了相同数量的块的内容,留下了事件。
UPD:是的,vue 只是更改块的 id 和内容,而不是从 dom 中删除它们并重新创建它们。如何改变这种行为?
codepen上的完整示例
我自己想通了。Vue 并没有真正完全重绘块。因此,来自 jsPlumb 的事件和类仍保留在它们上。要强制 Vue 完全重绘块,您需要通过显式添加属性来告诉它它们是不同的
key
。值必须是唯一的,比如 id,那么 Vue 就会明白这些是不同的块。