当容器具有隐藏项时,jQuery UI可排序拖动启动很慢

pod*_*nov 6 jquery-ui

我有一个无序的'源'列表,最多可包含大约1,000个列表项.我希望能够将源列表中的项目拖动到连接的"目标"列表中.我的一切工作都很顺利,直到我的源列表被过滤.我正在使用jquery quicksearch插件来过滤(搜索)我的源列表.过滤器通过设置'display:none;'来完成.对于与搜索不匹配的项目.

当隐藏源列表中的1..n项时,拖动操作在启动时不流畅.意思是,我点击我要拖动的项目,在屏幕上移动我的鼠标,但是我拖动的项目在我启动拖动后大约一整秒才出现在我的光标下.

为了诊断,我已经将我的用例缩减到了一个我要排序的列表.我已经完全取消了对quicksearch的使用,只需将我的一半列表项硬编码为隐藏.我仍然能够重现'非流动'的行为.我的例子在这里:

http://pastebin.com/g0mVE6sc

如果我从我的示例中的列表中删除溢出样式,性能会好一点,但仍然比我希望看到的要慢.

在我开始考虑其他选择之前,有没有人对我有任何建议?

提前致谢.

Did*_*hys 13

正如你在这个jsferf例子中看到的那样,计算outerWidth()/ outerHeight()(这是插件的作用 - 见下文)隐藏元素(显示无)比可见元素慢得多,这是通过style属性或类.

我发现绕过这个并且仍然实现相同结果的唯一方法是将元素高度设置为隐藏,而不是使用display属性,无论是使用样式atttibute还是类:

<li style="height: 0;">b</li>
<li class="hidden">b</li>

.hidden { height: 0 }
Run Code Online (Sandbox Code Playgroud)

DEMO(带课程) - DEMO(带风格attr)


在拖动元素时,sortable会发生什么?

开始拖动时,插件会刷新所有项目的列表并重新计算所有元素的位置.插件实际上是outerWidth和outerHeight:

_mouseStart: function(event, overrideHandle, noActivation) {
    ...
    //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
    this.refreshPositions();
    ...
}

refreshPositions: function(fast) {
    ...
    for (var i = this.items.length - 1; i >= 0; i--) {
        var item = this.items[i];
        ...
        if (!fast) {
            item.width = t.outerWidth();
            item.height = t.outerHeight();
        }
        var p = t.offset();
        item.left = p.left;
        item.top = p.top;
    };
    ...
    return this;
},?
Run Code Online (Sandbox Code Playgroud)


小智 6

如果您仍想使用display:none,这是对Didier的答案中指定的jQuery UI源的简单修复:

if (!fast) {
    if(item.item.css('display') === 'none') {
        item.width = 0;
        item.height = 0;
    }
    else {
        item.width = t.outerWidth();
        item.height = t.outerHeight();
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我关于stackoverflow的第一篇文章,所以如果我弄乱了,请告诉我.


Dan*_*nny 5

我也有类似的问题,但隐藏的drop容器而不是可排序的项目.这是我的解决方案,将Jordan的答案应用于可排序项目及其容器,并简单地替换relvent方法.

$.ui.sortable.prototype.refreshPositions = function(fast) {  
    //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
    if(this.offsetParent && this.helper) {
        this.offset.parent = this._getParentOffset();
    }

    for (var i = this.items.length - 1; i >= 0; i--){
        var item = this.items[i];

        //We ignore calculating positions of all connected containers when we're not over them
        if(item.instance != this.currentContainer && this.currentContainer && item.item[0] != this.currentItem[0])
            continue;

        var t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;

        if (!fast) {
            /********** MODIFICATION ***********/

            if(item.item.css('display') === 'none') {
                item.width = 0;
                item.height = 0;                    
            } else {
                item.width = t.outerWidth();
                item.height = t.outerHeight();
            }

            /********** END MODIFICATION ***********/
        }

        var p = t.offset();
        item.left = p.left;
        item.top = p.top;
    };

    if(this.options.custom && this.options.custom.refreshContainers) {
        this.options.custom.refreshContainers.call(this);
    } else {
        for (var i = this.containers.length - 1; i >= 0; i--){

            /********** MODIFICATION ***********/

            if (this.containers[i].element.css('display') == 'none') {
                this.containers[i].containerCache.left = 0;
                this.containers[i].containerCache.top = 0;
                this.containers[i].containerCache.width = 0;
                this.containers[i].containerCache.height = 0;
            } else {
                var p = this.containers[i].element.offset();
                this.containers[i].containerCache.left = p.left;
                this.containers[i].containerCache.top = p.top;
                this.containers[i].containerCache.width = this.containers[i].element.outerWidth();
                this.containers[i].containerCache.height = this.containers[i].element.outerHeight();
            }

            /********** END MODIFICATION ***********/
        };
    }

    return this;
};
Run Code Online (Sandbox Code Playgroud)