当您开始拖动一个 draggable
时,jQuery UI会内部运行以下代码以确定哪些 droppable
可以接收 draggable
。
var m = $.ui.ddmanager.droppables[t.options.scope] || [];
var type = event ? event.type : null;
var list = (t.currentItem || t.element).find(":data(droppable)").andSelf();
droppablesLoop: for (var i = 0; i < m.length; i++) {
if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) continue;
for (var j=0; j < list.length; j++) { if(list[j] == m[i].element[0]) { m[i].proportions.height = 0; continue droppablesLoop; } };
m[i].visible = m[i].element.css("display") != "none"; if(!m[i].visible) continue;
if(type == "mousedown") m[i]._activate.call(m[i], event);
m[i].offset = m[i].element.offset();
m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight };
}
如你所见,这段代码非常复杂,这也就解释了为什么每次开始拖动都会出现缓慢的表现。
注意,在 droppablesLoop 中检查的第一件事是 droppable 是否已禁用。
因此,为了提高性能,您可以始终手动禁用相应的 droppable 小部件,这将使您快速跳出上面的代码块。可以通过使用 draggable 上的 start 事件来实现这一点,该事件将首先触发。
$('.draggable').draggable({
start: function() {
$('.invalid-droppable-elements').droppable('option', 'disabled', true);
},
stop: function() {
$('.invalid-droppable-elements').droppable('option', 'disabled', false);
}
});
这基本上让你自己实现
accept
/
scope
逻辑,并且性能影响取决于你的算法。不过实现起来应该不会太难。插件之所以这么慢,是因为它们必须处理很多不同的情况。
jQuery UI不支持向单个
draggable
/
droppable
元素添加多个作用域,但您可以自己开发此功能。
我编写了一个示例,展示在这里-
http://jsfiddle.net/tj_vantoll/TgQTP/1/。