JQuery:在dragstart事件上更改DOM会立即触发dragend吗? [英] JQuery: Changing the DOM on dragstart event fires dragend immediately?

查看:122
本文介绍了JQuery:在dragstart事件上更改DOM会立即触发dragend吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了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, the dragend 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 the dragend handler before you stop dragging, and therefore, it appears as if the dragend 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆