【问题标题】:JQuery: Changing the DOM on dragstart event fires dragend immediately?JQuery:在 dragstart 事件上更改 DOM 会立即触发 dragend?
【发布时间】:2015-04-09 03:08:00
【问题描述】:

我遇到了 Chrome 和 Opera 的错误,我想知道它是否已知,如果已知,是否有解决方案?

如果我在 dragstart 事件上更改 DOM,它会立即触发 dragend 事件?!这是一个错误还是背后有什么原因?仅在 Chrome 和 Opera 中发生。 Firefox 有效。

感谢每一个回答。

$('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");

编辑:

将 DOM Change 放入 setTimeout 函数中似乎可以解决问题!

【问题讨论】:

  • 有人可以确认这是错误还是正常行为?它似乎也影响了 Firefox。
  • @thelolcat 可能重复stackoverflow.com/a/15114255/2646526? JQuery 文档谈论使用dragstop,而不是dragend。所以在 jQuery 中没有定义行为来处理dragend
  • $("#plugin_loginlogout_pfcontainer_" + dragProfilefieldSrcElformid) 在您拖动的元素内还是在其他地方?
  • ".plugin_loginlogout_pf" 后面的dragend 函数是什么?

标签: javascript jquery


【解决方案1】:

似乎不同的浏览器对长时间运行操作表现出不同的行为。

JavaScript 有一个线程,可以在同一个队列中运行所有指令。每个队列项目按顺序运行,一旦项目完成执行,下一个项目(来自队列)将被抓取并运行。

长时间运行操作的罪魁祸首是您尝试对 DOM 进行的更改(我假设在此之前使用 find() 进行大量搜索,这将为每个匹配的元素运行 DOM 操作 )。

当你拖动元素时会发生什么,dragstart 处理程序中的所有代码行,当你停止拖动时,dragend 处理程序分别被推送到消息队列中以便连续执行。然而,DOM 操作 比在您停止拖动之前执行 dragend 处理程序需要更多的时间(可能多几毫秒),因此,看起来好像 dragend 被触发了太快了。

注意: 有时代码块创建一个新事件,因此被推到浏览器事件队列的末尾( 或者可能在正在运行的项目之后的某个地方),从而导致稍后执行。 (我想它的性质因浏览器而异。)

您的代码的 DOM 操作部分可能在 Chrome 和 Opera 中遇到这样的问题,尽管我不确定。

setTimeout(fn, 0) 把戏

这种情况的解决方法是将长时间运行的操作块包装setTimeout 函数中,时间为0

(您可以认为这是告诉浏览器运行您的代码部分,根本没有时间!,而不是字面意思。)

一旦代码块执行完毕,浏览器将搜索等待运行的可用项目,setTimeoutsetInterval 将在第一个可用时刻被推送到队列中。

在您的特定情况下,诀窍是 setTimeout 推迟 DOM 的执行比 @ 更改到更晚的时间(至少 0) 987654335@ 事件处理程序,从而给人的印象好像是在 DOM 更改后触发了 dragend 事件。

@DVK here 有一篇很棒的帖子解释了为什么setTimeout(fn, 0) 有时很有用。也请检查他的JSfiddle(在 Chrome 中)。

更新

正如@MojoJojo 和@Pradeep 所指出的,Webkit 浏览器(尤其是旧版本的 Chrome)似乎存在drag 事件的问题。但是,我尝试在 Chrome 版本 47.0.2526.106(截至 2016 年 1 月 11 日的最新版本)中重现该错误,并且drag 事件触发时没有任何违规行为。

无论如何,即使存在错误,setTimeout 技巧仍然适用于解决问题。

【讨论】:

  • setTimeout() 解决方法在 Firefox 中存在问题,请参阅我的答案以获得更稳定的替代方案。
【解决方案2】:

只需尝试将您的 DOM 操作放在 dragstart 的 drag 事件中即可:)

【讨论】:

    【解决方案3】:

    我认为这是一个小故障/错误,否则我们可以说这就是浏览器的工作方式,因为我们正在执行 DOM 操作,这可能会导致重新绘制整个 DOM,在 dragStart 事件中操作 DOM 会导致这个问题,shift对 dragEnter 的 DOM 操作可能会解决这个问题。

    另一种解决方案可能是设置您已经提到的 setTimeout。

    【讨论】:

      【解决方案4】:

      没有 jquery 的作品

          var draggable = document.getElementById('draggable'),
            test = document.getElementById('test');
      
          document.addEventListener("dragend", function(event) {
            // reset the transparency
            console.log('dragend');
          }, false);
      
          draggable.addEventListener('dragstart', function(event) {
            test.style.color = 'red';
            draggable.style.backgroundColor = 'gray';
          }, false);
      

      http://jsfiddle.net/nwkv75ot/4/

      【讨论】:

        【解决方案5】:

        这似乎是 Chrome 中的一个问题 https://groups.google.com/a/chromium.org/forum/?fromgroups=#!msg/chromium-bugs/YHs3orFC8Dc/ryT25b7J-NwJ

        您使用的是哪个版本的 Chrome?

        【讨论】:

          【解决方案6】:

          我发现 setTimeout() 解决方法在 Firefox 中非常有问题。例如,当您在拖动后立即释放鼠标按钮时,dragstart 中的上下文可能不再可访问,脚本可能会崩溃。尤其是与 dragend 事件结合使用时。

          我创建了以下程序,这使我的脚本更加可靠:

          $('html').on('dragstart', '.somelement', function(e){
          
              // Bind 'drag' event only once (gets triggered every 350ms)
              $('html').one('drag', function(){
                   // modify DOM here
              });
          });
          
          $('html').on('dragend', '.somelement', function(e){
          
              // Edge might fire 'dragend' before executing the 'drag' event within 'dragstart'
              $('html').unbind('drag');
          
          });
          

          【讨论】:

            猜你喜欢
            • 2020-03-29
            • 2013-11-07
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-12-18
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多