【问题标题】:Possible to set event.dataTransfer asynchronously after drag start?可以在拖动开始后异步设置 event.dataTransfer 吗?
【发布时间】:2016-08-06 04:45:39
【问题描述】:

目前我正在处理一个需要在拖动开始后更改附加到拖动元素的数据的场景。基本上拖放区是输入字段或文本区域,所以我想使用本机 event.dataTransfer.setData,因为本机拖放可以使插入符号随鼠标移动。

如果我只是在dragstart 事件的侦听器中同步调用setData(),一切都会在开始时完美运行。

dragItem.addEventListener("dragstart",function(event){  
     event.dataTransfer.setData("text/plain","data set in dragstart");
}) 

但是,我的情况可能是数据来自异步回调函数,例如 AJAX 请求。然后我尝试在这个回调函数中调用setData(),但似乎没有成功设置。

dragItem.addEventListener("dragstart",function(event){

  event.dataTransfer.setData("text/plain","data set in dragstart");

  //like a callback in Ajax or resolve function of a promise.
  setTimeout(function(){
    console.log("attempt to set data asynchonrously after drag start");
    event.dataTransfer.setData("text/plain","asynchonrously set data");

    //looks like failed, the console output is empty, even not the original set one
    console.log(event.dataTransfer.getData("text/plain"));
  },200)

}) 

我还尝试更改拖放区的dragenter 甚至drop 事件侦听器中的数据。但仍然没有运气。

这个plunker 显示了我的尝试。

然后我参考MDN API document 找到dataTransfer 对象的官方api 描述。但是对于拖动开始后异步使用setData之类的问题没有任何问题。一件非常奇怪的事情是,如果我尝试比较 dragstartdrop 事件中的两个 dataTransfer 引用,它们不是同一个对象。现在我不知道实际发生了什么。

所以我的问题是

  1. 是否可以在使用原生 API 开始拖动后将数据设置在 dataTransfer 中(不使用 event.preventDefault)?
  2. 如果第一个问题的答案是否定的,我可以尝试哪种解决方法? 我可以考虑如何保存和获取要传输的数据。我主要担心的是,如果在drop 上使用event.preventDefault(),那么用鼠标移动插入符号并不容易,就像原生拖放一样。

【问题讨论】:

  • 异步设置event.dataTransfer的目的是什么?你想达到什么目的?

标签: javascript jquery html drag-and-drop dom-events


【解决方案1】:

这是你的答案。 首先,您只能在 dragstart 事件中设置数据。因此,每次任何 dragstart 事件启动时,它都会设置值,而您异步设置的内容无论如何都不会得到反映。

因此,您可以做的一件事是拥有一个全局对象并将其设置为拖动开始事件,如下所示:

var someObj = {
   asd : 'something'
}

并在你的dragstart回调中设置,像这样:

dragItem.addEventListener("dragstart",function(event){

      event.dataTransfer.setData("text/plain", someObj.asd);
      dataTransferObject = event.dataTransfer;

      setTimeout(function(){
        console.log("attempt to set data asynchonrously after drag start");
        //event.dataTransfer.setData("text/plain","asynchonrously set data");

        someObj.asd = 'asynchonrously';
        //looks like failed, the console output is empty
        console.log(event.dataTransfer.getData("text/plain"));
      }, 100)

    })    

Object 默认是引用类型。 现在,您可以将 someObj.asd 设置为您想要的任何值,您将看到反映的新值。但是这种方法有一个问题,值会在 drop 发生后反映,意味着事件结束后。

所以,要解决您的问题,您可以做的是不要在 dragstart 上设置任何值,只需在拖动开始时为 someObj.asd 设置一些值并使用 someObj.asd 放置。

这是我要解释的链接: https://plnkr.co/edit/SZhI9lGRI37eEd1nWfhn?p=preview

在放置事件时查看控制台您将在那里看到反映的值。

不要看到 UI 只是为了控制台

【讨论】:

  • 感谢您的回答。将其保存在全局对象中是个好主意。但我不想实现的是将保存的文本插入到该文本区域或光标位置的内容可编辑 div(跟踪鼠标位置,如本机)。因此,在对第一个问题给出“否”之后,解决方法的关键问题是如何使用放置时的全局对象在正确的位置插入文本。
  • 你可以编写 javascript 来为你做这件事。
  • 嗯,这是真的。但如果这很容易做到,我就不会那么挣扎了。我也找不到任何图书馆帮助我实现这一目标。所以我仍然面临这个问题,无法找到用你当前的答案解决它的方法。我需要 ui 才能正确更新。
猜你喜欢
  • 2022-07-09
  • 2011-11-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-24
  • 2011-03-25
  • 1970-01-01
  • 2011-10-25
相关资源
最近更新 更多