JQuery:在dragstart事件上更改DOM会立即触发dragend吗? [英] JQuery: Changing the DOM on dragstart event fires dragend immediately?
问题描述
我遇到了Chrome和Opera的错误,我想知道它是否已知,如果有,是否有解决方案?
i came across a bug for Chrome and Opera and i would like to know if its known and if so, is there a solution?
如果我更改了DOM在dragstart事件中,它会立即触发dragend事件?!这是一个错误还是背后有一些原因?只发生在Chrome和Opera中。 Firefox可以工作。
If i change the DOM on the dragstart event it immediately fires the dragend event?! Is this a bug or is there some reason behind it? Only happens in Chrome and Opera. Firefox works.
我感谢每一个答案。
$('body').on({
dragstart: function(e) {
dragProfilefieldSrcElformid = $(this).attr("data-profilefieldid-formid");
e.dataTransfer = e.originalEvent.dataTransfer;
e.dataTransfer.effectAllowed = 'move';
e.dataTransfer.setData('text/html', $(this).attr("data-profilefieldid"));
// Changing the DOM, fires the dragend Event in Chrome?
$("#plugin_loginlogout_pfcontainer_" + dragProfilefieldSrcElformid).find(".plugin_loginlogout_pf_entryfield").addClass("highlight"); // This doesn't work in Chrome and Opera, but in Firefox
},
dragend: function() {
console.log("dragend");
}
".plugin_loginlogout_pf");
编辑:
投入setTimeout函数中的DOM更改似乎解决了这个问题!
Putting the DOM Change in a setTimeout Function seems to solve the problem!
推荐答案
似乎不同的浏览器对表现出不同的行为长时间运行操作。
It seems that different browsers manifest different behaviors towards long running operations.
JavaScript有一个线程可以在同一队列中运行所有指令。每个队列项都按顺序运行,一旦项完成执行,下一个项( from queue )就会被抓取并运行。
JavaScript has a single thread that runs all of your instructions in the same queue. Each queue item is run in sequence and once the item has finished execution, the next item (from the queue) is grabbed and run.
长时间运行操作的罪魁祸首是你试图给DOM带来的变化(我假设之前是使用 find()
进行大量搜索,它将运行每个匹配元素的DOM操作)。
The culprit for long running operation is the change you try to bring to the DOM (which I assume is preceded by a heavy search using find()
that will run the DOM manipulation for each matched element).
拖动元素时会发生什么,
dragstart中的所有代码行
handler,当你停止拖动时,dragend
处理程序分别被推送到消息队列,以便顺序执行。但是,在停止拖动之前, DOM操作比执行dragend
处理程序花费更多时间(可能要多几毫秒),并且因此,看起来好像dragend
太快了。
What happens as you drag the element is that, all lines of code in the
dragstart
handler, and as you stop dragging, thedragend
handler are pushed to the message queue respectively in order to be executed serially. However the DOM manipulation is taking more time (probably a few milliseconds more) to execute than the execution of thedragend
handler before you stop dragging, and therefore, it appears as if thedragend
fired way too soon.
注意:有时代码块 会创建一个新事件 ,因此被推送到浏览器事件队列的末尾(或可能在正在运行的项目之后的某个地方,导致稍后的执行。 (我认为它的性质因浏览器而异。)
Note: Sometimes block(s) of code create a new event and hence are pushed to the end of the browser event queue (or maybe somewhere after the item that's being run), resulting in a later execution. (I suppose the nature of it differs from browser to browser.)
DOM操作部分代码可能在Chrome和Opera中遇到这样的问题,虽然我不确定。
The DOM manipulation part of your code might face such an issue in Chrome and Opera, though I'm not sure.
此类情况的解决方法是在 setTimeout $中换行长时间运行的操作块c $ c>函数
0
时间。
The workaround for such situations is to wrap the long running operation block in a setTimeout
function with 0
time.
(您可以将此视为告诉浏览器运行代码的一部分,在 根本没有时间! ,但不是字面意思。)
(You can think of this as telling the browser to run the part of your code, in no time at all!, not literally though.)
一旦代码块执行完毕,浏览器将搜索等待运行的可用项目,以及 setTimeout
或的项目setInterval
将在第一个可用时刻推送到队列。
Once a block of code has done execution, the browser will search for the available items waiting to be run, and the ones with setTimeout
or setInterval
will be pushed to the queue upon first available moment.
在您的特定情况下,诀窍是 setTimeout
推迟将DOM更改执行到lat时间(至少 0
秒)比 dragend
事件处理程序,从而给出好像在DOM更改后触发 dragend
事件的印象。
In your particular case, the trick is that setTimeout
defers the execution of DOM change to a later time (at least 0
seconds) than the dragend
event handler, thereby giving the impression as if the dragend
event fired after the DOM change.
@DVK有一篇很棒的文章 此处 解释为什么 setTimeout( fn,0)
有时很有用。请检查他(在Chrome中) JSfiddle 。
There is a great post by @DVK here explaining why setTimeout(fn, 0)
is sometimes useful. Do check the JSfiddle by him (in Chrome) as well.
正如@MojoJojo和@Pradeep所指出的那样,似乎Webkit浏览器(特别是旧版本的Chrome)存在拖动
事件。但是,我尝试重现Chrome版本47.0.2526.106(截至2016年1月11日的最新版本)中的错误,以及拖动
事件而没有任何违规行为。
As pointed by @MojoJojo and @Pradeep, it seems that Webkit browsers (older versions of Chrome in particular) have an issue with drag
events. However, I tried to reproduce the bug in Chrome Version 47.0.2526.106 (newest version as of 11th January 2016), and the drag
events fired without any irregularities.
无论如何,即使有错误, setTimeout
技巧仍然适用于适当的解决方法问题。
Anyway, even if there was a bug, the setTimeout
trick still applies as a proper workaround for the issue.
这篇关于JQuery:在dragstart事件上更改DOM会立即触发dragend吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!