У меня здесь небольшие проблемы с использованием jQuery draggable / dropppable в моем компоненте представления created().
Если я использую это в <script>, он работает отлично, однако, как только я его выделю, canvas.droppable() никогда не вызывается. Я подозреваю, что это мое незнание идиом, но некоторая помощь была бы отличной!
Код:
Vue.component('design', {
props: ['user'],
/**
* The component's data.
*/
data() {
return {
diagram: [
{
"_id": 1537472962719,
"position": {
"top": 104,
"left": 407.29998779296875
},
"type": "TOOL-1"
},
{
"_id": 1537473836985,
"position": {
"top": 239,
"left": 643.2999877929688
},
"type": "TOOL-1"
},
{
"_id": 1537473839676,
"position": {
"top": 136.39999389648438,
"left": 228.29998779296875
},
"type": "TOOL-2"
},
{
"_id": 1537473843399,
"position": {
"top": 209.8000030517578,
"left": 422.29998779296875
},
"type": "TOOL-3"
}
],
};
},
/**
* The component has been created by Vue.
*/
created() {
let self = this;
$(document).ready(function(){
var canvas = $(".canvas");
var tools = $(".tools");
$(".tool").draggable({
helper: "clone"
});
if (!self.diagram.length == 0) {
renderDiagram(self.diagram);
}
canvas.droppable({
drop: function(event, ui) {
console.info('dropped');
var node = {
_id: (new Date).getTime(),
position: ui.helper.position()
};
node.position.left -= canvas.position().left;
if (ui.helper.hasClass("tool-1")){
node.type = "TOOL-1";
} else if (ui.helper.hasClass("tool-2")){
node.type = "TOOL-2";
} else if (ui.helper.hasClass("tool-3")){
node.type = "TOOL-3";
} else {
return;
}
self.diagram.push(node);
renderDiagram(self.diagram);
}
});
function renderDiagram(diagram) {
canvas.empty();
for (var d in diagram) {
var node = diagram[d];
var html = "";
if (node.type === "TOOL-1") {
html = "<h3>TOOL 1</h3>";
} else if (node.type === "TOOL-2") {
html = "<h3>TOOL 2</h3>";
} else if (node.type === "TOOL-3") {
html = "<h3>TOOL 3</h3>";
}
var dom = $(html).css({
"position": "absolute",
"top": node.position.top,
"left": node.position.left
}).draggable({
stop: function(event, ui) {
var id = ui.helper.attr("id");
for (var i in diagram) {
if (diagram[i]._id == id) {
diagram[i].position.top = ui.position.top;
diagram[i].position.left = ui.position.left;
}
}
}
}).attr("id", node._id);
canvas.append(dom);
}
}
});
},
methods: {
//
}
});
Для краткости; Imaging diagram[] - это фиктивный шаблон для данных, которые в конечном итоге будут вызываться из базы данных, захваченной методом Vue. Элементы в этом массиве рисуются на холсте при загрузке страницы, и их можно перетаскивать, при этом их положение обновляется в daigram[], однако попытка перетащить новые элементы на холст приводит к тому, что droppable() не вызывается, и, следовательно, элементы не добавлен к DOM.
Извините за отсутствие опыта работы с JS в целом!
ОБНОВИТЬ:
Вот шаблон клинка для справки
<design :user = "user" inline-template>
<div class = "container-fluid"
style = "position: absolute;bottom: 0px;top: 0px;left: 0px;right: 0px;">
<h1>Drag and Drop Tools Onto Canvas</h1>
<div class = "row"
style = "height: 100%;position: relative;">
<div class = "col-xs-3 tools"
style = "background-color: #9acfea;position: absolute;top: 0px;bottom: 0px;left: 0px;">
<h2>Tools</h2>
<h3 class = "tool tool-1">Tool 1</h3>
<h3 class = "tool tool-2">Tool 2</h3>
<h3 class = "tool tool-3">Tool 3</h3>
</div>
<div class = "col-xs-9 canvas"
style = "background-color: beige;">
</div>
</div>
</div>
</design>



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Мне удалось заставить это работать. Похоже, я неправильно сослался на переменную diagram. Это работает:
Vue.component('design', {
props: ['user'],
/**
* The component's data.
*/
data() {
return {
diagram: [],
};
},
mounted() {
// Get the canvas
let self = this;
var canvas = $(".canvas");
var resource = $(".resource");
// enable drag on the resources
resource.draggable({
helper: "clone"
});
// configure droppable on the canvas
canvas.droppable({
// define allowed elements
accept: resource,
// configure the drop event
drop: function(event, ui) {
// create object for dropped element
var node = {
_id: (new Date).getTime(),
position: ui.helper.position(),
};
// repaint left due to sidebar position
node.position.left -= canvas.position().left;
// Append type to object
if (ui.helper.hasClass("test")) {
node.type = "test";
}
return;
}
// push the element onto the diagram array
self.diagram.push(node);
render();
}
});
// Define the render function to add resources to the diagram
function render() {
// Here we empty the canvas so we can re-draw it
canvas.empty();
// Traverse the resource array and action
self.diagram.forEach(r => {
// Grab the individal node
var node = r;
// Creat empty html variable
var html = "";
// Here we generate our html for when the element has been dropped
if (node.type === 'test') {
html = "<h3>Test</h3>"
}
// Generate the css for the dom element
var dom = $(html).css({
"position": "absolute",
"top": node.position.top,
"left": node.position.left
})
// Configure draggable of dropped items
.draggable({
stop: function(event, ui) {
var id = ui.helper.attr("id");
for (var i in self.diagram) {
if (self.diagram[i]._id == id) {
self.diagram[i].position.top = ui.position.top;
self.diagram[i].position.left = ui.position.left;
}
}
// render();
}
}).attr("id", node._id);
// Append the dom element to the canvas
canvas.append(dom);
})
}
}
});
Также, как добавленное примечание: я заметил низкую производительность при перетаскивании. Отключение переходов следующим образом исправило это:
ul.projects li:not(.ui-sortable-helper) {
float: left;
margin: 0px 6.5px 12px;
cursor: pointer;
-webkit-transition: all 0.2s linear;
-moz-transition: all 0.2s linear;
-ms-transition: all 0.2s linear;
-o-transition: all 0.2s linear;
transition: all 0.2s linear;
}
Наконец, вот HTML, с которым я работаю (bootstrap 4):
<div class = "container-fluid" style = "height:100vh;">
<div class = "row" style = "height:100%;">
<div class = "col-md-3">
<h3 class = "test resource">AWS Instance</h3>
</div>
<div class = "canvas col-md-9">
{{--Things here--}}
</div>
</div>
</div>