我希望有几类draggables,每一类都对应一类droppables。但另外,我想要一个单独的“垃圾箱”,可以放下所有可拖动的垃圾箱,直到可以找到合适的垃圾箱。
现在,使用accept函数可以轻松实现。但是,我最多可以有20个班级,每个班级有30-40个可拖动/可放置。因此,如果我使用“接受”功能,那么当我拿起一个可拖动的时候,我的镀铬会冻结,因为它会对屏幕上的每个可放置的测试进行测试:(
如果我使用'scope'属性,这可以解决,因为它似乎使用了一些不同的方式。但是,当我使用示波器时,我似乎无法实现“垃圾箱”概念,因为它只能有一个示波器!
有没有办法绕过这个问题?给可拖动的多个范围,或给垃圾箱多个范围?或者也许是其他一些我想不到的解决方案?
答案 0 :(得分:8)
每当您开始拖动draggable
以确定哪些droppable
有资格接收draggable
时,内部jQuery UI将运行以下代码。
var m = $.ui.ddmanager.droppables[t.options.scope] || [];
var type = event ? event.type : null; // workaround for #2317
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; //No disabled and non-accepted
for (var j=0; j < list.length; j++) { if(list[j] == m[i].element[0]) { m[i].proportions.height = 0; continue droppablesLoop; } }; //Filter out elements in the current dragged item
m[i].visible = m[i].element.css("display") != "none"; if(!m[i].visible) continue; //If the element is not visible, continue
if(type == "mousedown") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables
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
小部件,这将使您快速跳出上面的代码块。您可以使用start
上的draggable
事件执行此操作,该事件将首先触发。
$('.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/。