通过dataTransfer传递对象

sar*_*ink 38 html jquery drag-and-drop

我试图找出一种通过javascript的event.dataTransfer传递本机对象的方法来进行拖放.我正在编写CMS的前端编辑器部分,并希望用户能够拖放元素(许多不同类型,从文件到图像到HTML片段到几乎任何东西).这就是为什么我想传递一个真实的对象,所以我可以附加数据来指定必要的东西,以便知道如何渲染它.

一种解决方法是使用jQuery的.data()将对象附加到页面上的其他内容,然后简单地在setData中传递选择器字符串...但我并不特别喜欢该hack.

这也可以通过jQuery UI的draggable/droppable来解决(我并不完全反对使用任何库),但由于dropzone位于iframe中,这实际上是最新jQuery UI中的文档错误(1.10.2) ).另外,如果可能的话,我更愿意本地做.这个应用程序中已经有足够的库.

这是问题所在:http://jsfiddle.net/AHnh8/

var foo = {foo: "foo", bar: "bar"};

$dragme.on("dragstart", function(e) {
    e.originalEvent.dataTransfer.setData("foo", foo);
});

$dropzone.on("dragenter", function(e) { e.preventDefault(); });
$dropzone.on("dragover", function(e) { e.preventDefault(); });
$dropzone.on("drop", function(e) {
    console.log(e.originalEvent.dataTransfer.getData("foo")); // [Object object]
    console.log(typeof e.originalEvent.dataTransfer.getData("foo")); // string
});
Run Code Online (Sandbox Code Playgroud)

现在,在阅读了规范后,我完全理解为什么会失败.我不明白的是,如何最终实现我想要的.

谢谢

小智 51

您应该JSON.stringify在使用之前将对象传递给setData您,因为您只能存储字符串.

var j = JSON.stringify(foo);
e.originalEvent.dataTransfer.setData("foo", j);
Run Code Online (Sandbox Code Playgroud)

反过来,你必须将字符串重新转换为对象:

var obj = JSON.parse(e.originalEvent.dataTransfer.getData("foo"));
console.log("foo is:", obj);
Run Code Online (Sandbox Code Playgroud)

看到这个工作小提琴

  • 在这种情况下,我认为这种方式效率很低.编码/解码过程是额外的开销,并且对象将被不必要地复制.临时全局数组似乎是暂时处理此问题的最佳方法. (7认同)
  • 除非你丢弃大量的JSON对象,否则我看不出这会是多么低效.这样你也可以从其他标签中删除东西! (3认同)
  • 这不仅仅是 json 编码/解码开销。更重要的是你失去了对原始对象的引用,所以你不能轻易改变它。例如,这是 Vuejs 中的一个问题,其中一切都基于数据(对象、数组),并且在拖放操作中直接引用它们会很方便。 (3认同)
  • 在我发布之后我也考虑过这个,虽然我仍然觉得应该有办法传递一个对象? (2认同)

Jim*_*Boy 5

也许我要提出的建议是错误的(如果是这样,我会很高兴听到原因)。为什么不在 dragstart 侦听器中设置一个变量来引用您需要的内容,例如:

//global variable
var obj;

//set the global variable to wahtever you wish in the dragstart:
$dragme.on("dragstart", function(e) {
    obj = foo;
    //or even obj = document.getElementById("some element's id");
});

//use this obj in the drop listener.
$dropzone.on("drop", function(e) {
    obj.doWahtEver();
});
Run Code Online (Sandbox Code Playgroud)

  • bc globals = :( .. 有很多像这样的琐碎解决方法。我最初发布这个问题是因为我想知道您是否可以通过 dataTransfer 传递对象。事实证明您不能。 (5认同)