如何解决拖动事件的性能问题

Posted

技术标签:

【中文标题】如何解决拖动事件的性能问题【英文标题】:How to fix performance issue with drag event 【发布时间】:2016-01-18 12:24:54 【问题描述】:

我有一个 500 行的表格,每行大约有 50 个 html 元素,所以它非常复杂。

在同一窗口的另一个窗格中,我有一个包含 10 个拖放区的列表。

我的表格的每一行都具有可拖动属性,因此可以将其拖放到 10 个放置区域之一中。

我正在使用 dragenter 和 dragleave 事件来检测拖动鼠标何时悬停在放置区域上,并在放置区域位于光标下方时在放置区域周围添加一个简单的边框。

如果我的表格少于 100 行,则边框突出显示速度非常快。

如果有 500 行,它会滞后很长时间,以至于无法接受。

不知道为什么表格的复杂度(拖拽的来源)会直接影响到dragenter和dragleave事件的性能...

就好像为表格中的每个 html 元素发送了某种事件!

表格是这样的:

<div class="left_pane">
    <ul>
        <li><div class="dropzone">...</div></li>
        <li><div class="dropzone">...</div></li>
        ...
        <li><div class="dropzone">...</div></li>
    </ul>
</div>
<div class="right_pane">
    <table><tbody>
        <tr draggable="true">...</tr>
        <tr draggable="true">...</tr>
        ...
        <tr draggable="true">...</tr>
    </tbody></table>
</div>

如您所见,我可以从右窗格中拖动表格行并将其放在左窗格的列表元素上。

javascript 代码(使用 ext-js)如下所示:

init_component: function() 
    var left_pane_div = Ext.get(sg_find('div.left_pane',document.body));
    var right_pane_div = Ext.get(sg_find('div.righ_pane',document.body));

    // the following code is what's used while we hover over
    this.add_event(left_pane_div,'dragenter',this.on_document_dragenter);
    this.add_event(left_pane_div,'dragleave',this.on_document_dragleave);
    ...


on_document_dragenter: function(ext_e) 
    var e = ext_e.browserEvent;
    e.preventDefault();
    var t = Ext.get(e.target);
    if ( !t ) return;

    var drop_div = t.findParent('div.dropzone',document.body,true);
    if ( drop_div ) 
        drop_div.addClass( 'dropover' );
    
,

on_document_dragleave: function(ext_e) 
    var e = ext_e.browserEvent;
    e.preventDefault();
    var t = Ext.get(e.target);
    if ( !t ) return;

    var drop_div = t.findParent('div.dropzone',document.body,true);
    if ( drop_div ) 
        drop_div.removeClass( 'dropover' );
    
,

当用户将鼠标悬停在拖放区上时,我有一些 css 魔法来突出显示它。

如果表的行数超过 100 行,它会再次滞后。

要么是事件泵无法足够快地触发 dragenter 和 dragleave 事件,要么是我的左窗格中突出显示的 dropzone 导致在右窗格的表格上以某种方式重绘......

【问题讨论】:

代码示例肯定会有所帮助,即使它是简化版本。 使用轮廓而不是更改边框。突然出现的新边框将导致整个表格重排。这是表格执行速度较慢并因此不适合用作布局的另一个原因。另外,如果你可以只拖动一个按钮或图标而不是整行,它可能会更快...... 边框在不属于表格的放置区周围。我的放置区列表位于单独的窗格中。我可以尝试避免使我的 元素可拖动,但我必须说那将是不幸的。 我对这个问题做了很多调查,但仍然没有找到一个好的解决方案......似乎浏览器正在做很多工作来确定哪个元素在发送之前在光标下DragEnter 和 DragLeave 事件 【参考方案1】:

使用去抖动功能。更多详情:

https://levelup.gitconnected.com/debounce-in-javascript-improve-your-applications-performance-5b01855e086?gi=73510eb50568

【讨论】:

以上是关于如何解决拖动事件的性能问题的主要内容,如果未能解决你的问题,请参考以下文章

WPF 嵌入Winform GDI 开启AllowsTransparenc问题

如何解决 VB.NET 1.1 应用程序的性能下降?

基于事件驱动的高性能开源网络库libevent介绍及安装

js函数节流(解决频繁触发函数的性能问题)

「前端进阶」高性能渲染十万条数据(虚拟DOM解决方案)

阻止拖动事件的绝对定位元素