jQuery UI 在悬停时添加可放置的事件侦听器

Posted

技术标签:

【中文标题】jQuery UI 在悬停时添加可放置的事件侦听器【英文标题】:jQuery UI add droppable event listener while hovering 【发布时间】:2020-06-03 13:54:45 【问题描述】:

我想在拖动一个对象并悬停可放置对象时添加可放置事件侦听器。

这是我的代码:

$('.will-be-drag').draggable(
    helper: 'clone',
    drag: function (event, ui) 
        $('.will-be-drop').hover(function () 
            $(this).droppable(
                drop: function (event, ui) 
                    let item = ui.draggable;
                    console.log(item[0])
                    item.detach().appendTo($(this));
                
            );
        , function () 
            $(this).droppable('disable');
        );

    
);

而我的 html 是这样的:

<div class="will-be-drag"></div>
<div class="will-be-drag"></div>
<div class="will-be-drag"></div>

<?php
for($i = 0; $i <= 3000; $i++)
?>
    <div class="will-be-drop"></div>
<?php

?>

我这样做是因为性能问题。我有 3k 可放置的对象,拖动时它会冻结。它必须添加droppable eventlistener,仅拖动$('.will-be-drag') 对象并悬停$('.will-be-drop')

使用此代码它只在悬停时添加而不是在拖动时添加。

我该怎么做?

我想让 javascript 呼吸,设置 3k 可放置对象时已经晚了。只有 30-40 个可拖动元素。这是一张桌子。

【问题讨论】:

$('.will-be-drop').not(this).draggable("disable"); ? 不,我想添加仅可放置的悬停项目 你也可以放html代码吗? 好的,我放PHP代码 这不是使函数工作的最佳方式。我会在页面初始化时分配 droppable,然后您可以调整 accept 选项或将它们禁用直到悬停。 【参考方案1】:

这是一个悬停示例:

$(function() 
  $("#draggable").draggable();
  $("#droppable").droppable(
    drop: function(event, ui) 
      $(this)
        .find("p")
        .html("Dropped!");
    
  ).hover(function(e) 
    // IN
    $(this)
      .addClass("ui-state-highlight");
  , function(e) 
    // OUT
    $(this)
      .removeClass("ui-state-highlight");
  );
);
#draggable 
  width: 100px;
  height: 100px;
  padding: 0.5em;
  float: left;
  margin: 10px 10px 10px 0;


#droppable 
  width: 150px;
  height: 150px;
  padding: 0.5em;
  float: left;
  margin: 10px;
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<div id="draggable" class="ui-widget-content">
  <p>Drag me to my target</p>
</div>

<div id="droppable" class="ui-widget-header">
  <p>Drop here</p>
</div>

您可以看到,当您将鼠标悬停在 droppable 上时,它会突出显示。当你拖动时,它不会。我怀疑hover 事件不能在持久的mousedown 事件上冒泡。

建议这样做:

$(function() 
  function makeDrops(n) 
    var t = $(".ui-widget").eq(1);
    for (var i = 1; i <= n; i++) 
      $("<div>", 
        id: "drop-" + i,
        class: "will-be-drop ui-widget-content"
      ).appendTo(t);
    
  

  function inViewport(element, detectPartial) 
    element = $(element);
    detectPartial = (!!detectPartial); // if null or undefined, default to false

    var viewport = $(window),
      vpWidth = viewport.width(),
      vpHeight = viewport.height(),
      vpTop = viewport.scrollTop(),
      vpBottom = vpTop + vpHeight,
      vpLeft = viewport.scrollLeft(),
      vpRight = vpLeft + vpWidth,

      elementOffset = element.offset(),
      elementTopArea = elementOffset.top + ((detectPartial) ? element.height() : 0),
      elementBottomArea = elementOffset.top + ((detectPartial) ? 0 : element.height()),
      elementLeftArea = elementOffset.left + ((detectPartial) ? element.width() : 0),
      elementRightArea = elementOffset.left + ((detectPartial) ? 0 : element.width());

    return ((elementBottomArea <= vpBottom) && (elementTopArea >= vpTop)) && ((elementRightArea <= vpRight) && (elementLeftArea >= vpLeft));
  

  function markVisible(c) 
    c.each(function(i, el) 
      if (inViewport(el, true)) 
        $(el).addClass("visible");
      
    );
  

  makeDrops(3000);

  $(".will-be-drop").droppable(
    drop: function(event, ui) 
      let item = ui.draggable;
      console.log("Drag Item " + item.text().trim() + " dropped to " + $(this).attr("id"));
      item.detach().appendTo($(this));
    ,
    over: function() 
      $(this).addClass("ui-state-highlight");
    ,
    out: function() 
      $(this).removeClass("ui-state-highlight");
    
  ).droppable("disable");

  $('.will-be-drag').draggable(
    helper: 'clone',
    start: function(e, ui) 
      markVisible($(".will-be-drop"));
      $(".will-be-drop.visible").droppable("enable");
    ,
    drag: function(e, ui) 
      $(".will-be-drop.visible").droppable("disable").removeClass("visible");
      markVisible($(".will-be-drop"));
      $(".will-be-drop.visible").droppable("enable");
    ,
    stop: function(e, ui) 
      $(".will-be-drop").droppable("disable");
      $(".will-be-drop.ui-state-highlight").removeClass("ui-state-highlight");
    
  );
);
.will-be-drag 
  width: 50px;
  height: 50px;
  padding: 0.25em;
  float: left;
  margin: 10px 10px 10px 0;


.will-be-drop 
  width: 100px;
  height: 100px;
  padding: 0.25em;
  float: left;
  margin: 10px;
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<div class="ui-widget">
  <div class="will-be-drag ui-widget-content">A</div>
  <div class="will-be-drag ui-widget-content">B</div>
  <div class="will-be-drag ui-widget-content">C</div>
</div>
<div class="ui-widget">
</div>

您还可以使用:visible 或其他一些条件将一些初始化为可丢弃,以减少内存开销。请记住也要销毁它们,否则当用户在拖动时在页面中移动时,您只会堆积内存问题。

【讨论】:

谢谢和抱歉,但性能上没有区别,真的卡住了 @sundowatch 不,我没有用 3000 个项目对其进行测试。我已经更新了我的答案,是的,性能有点慢,但脚本并没有停止。如果页面上有更多元素和其他脚本,则内存资源可能会在某些浏览器上下降到脚本不再响应的状态。如果是这种情况,您可能会考虑根据滚动值初始化和销毁​​ droppable,并打开其中一组。也许使用:visible 选择器。 是的,这将是一个解决方案,但如果我能够在拖动所有内容时设法获取单元格(将要放置)就可以了 @sundowatch 由于拖动创建的 click-n-hold 活动,某些事件(如悬停)并不总是正确触发。所以鼠标位置或滚动位置条件在拖动过程中可能更好看。 @sundowatch 更新了关于悬停的扩展示例。

以上是关于jQuery UI 在悬停时添加可放置的事件侦听器的主要内容,如果未能解决你的问题,请参考以下文章

jQuery UI:使用容差触摸放置对象时的可拖动行为

jQuery UI droppable:悬停时调整元素大小不起作用

Jquery ui 可排序放置事件

在 jquery-ui datepicker 中的“今天”按钮上添加事件侦听器

jQuery UI - 放置事件后克隆可放置/可排序列表

拖动元素jquery ui时连续触发鼠标悬停事件?