【发布时间】:2019-08-05 23:57:37
【问题描述】:
我有一个使用 jQueryUI 可排序的列表。 根据插件的“更改”事件,我需要在拖动时跟踪元素的每一步。
但它只能在缓慢到正常的拖动中可靠地工作。在这些速度下,没有任何错误。但是如果用户拖动元素的速度相对较快(列表越大越频繁,因为鼠标有更多的空间来获得速度),“更改”事件会丢失一些步骤,因此一些有用的信息会随之丢失在控制台中没有抛出错误的方式。
显示问题:
https://jsfiddle.net/yhp3m6L8/2/
在这个 jsFiddle 中,您可以拖动一个元素并查看它的索引变化作为一个示例。在列表下方,拖动时,您将有一个控制台模拟跟踪 black 中的索引。
如果拖得相当快,您会看到其中一些索引变为红色。这就是问题。这意味着他们之前的位置在更改事件期间被可排序脚本忽略,原因我只是不明白。连续性被打破了,这种连续性对我的需求来说是最重要的。 速度是唯一破坏连续性的东西。但是无法跟上相当快的鼠标拖动速度的“更改”事件似乎很奇怪。
脚本:
其中一半是关于跟踪索引,因为 Sortable 有一种特殊的引用索引的方式,它取决于方向(上/下),但也取决于元素相对于其初始位置的当前位置(之前/之后) .因此,从视觉上理解这些索引所需的代码量最少。使用该脚本,该元素会以一种有序的方式获得直观的视觉索引,这是您希望看到的。
然而,这个脚本是问题的展示,可能不是问题(见下面的附注)。
脚本的另一半只是模拟一种用于调试目的的控制台。
我的猜测:
我可能错了,但我最终认为这是“更改”事件的跟踪问题,或者拖动的元素没有跟上鼠标光标(感觉它并不总是在相对较高的光标下速度)。 除非有我不知道的 Sortable 选项可供使用...
我认为这是其中一种情况,因为无论我尝试在“更改”事件中使用什么代码,我最终都会遇到这个差距问题。
HTML:
<html>
<body>
<div class="panel">
<ul class="panel_list">
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="ticked"></li>
<li class="unticked"></li>
<li class="unticked"></li>
<li class="unticked"></li>
</ul>
</div>
<div class='console'></div>
</body>
</html>
CSS:
.console{
width:100%;
}
.panel ul{
list-style-type:none;
width:30%;
}
.panel li{
height:29px;
border-bottom:1px solid #454d5a;
text-align: left;
vertical-align: middle;
line-height:29px;
padding-left:8px;
background: #666;
}
.panel_highlight{
height:29px;
background:#1c2128 !important;
}
.unticked{
color:#7c7a7d;
background:#222 !important;
}
jQuery:
// jQuery: 3.3.1
// jQueryUI: 1.11.4 (downgraded from 1.12.1, because of documented
// performance issues but...with no effect)
var origValue;
var oldInfo;
var c=0;
var x=0;
// LIST RELATED
//Just to have a visual on the indexes in the list.
$('li').each(function(){
$(this).data('idx',c++);
$(this).text(c);
})
c=0;
$( ".panel_list" ).sortable({
placeholder: 'panel_highlight',
items : '>li.ticked',
cancel : '>li.unticked',
tolerance : 'pointer',
axis : 'y',
opacity : 0.9,
start: function(event, ui){
// LIST RELATED
origValue = ui.item.data('idx');
// CONSOLE RELATED (initialise variables)
$('.console').html('');oldInfo='';
},
change: function(event, ui){
// LIST RELATED
var idx = ui.placeholder.prevAll().filter(':not(.ui-sortable-helper)').length;
var a=ui.placeholder.index();
var b=a+1;
//detect the direction of the dragging
if(idx - $(this).data('idx')==1)
{//downward dragging
//if the element is below its initial position (or x=1)
if((a<=origValue) || (x==1)){ui.item.text(b);x=0;}
//if the element is still above its initial position
else {ui.item.text(a);};
}
else
{//upward dragging
//if the element is still below its initial position
if(a<=origValue) {ui.item.text(b);x=1;}
//if the element is above its initial position
else {ui.item.text(a);};
};
$(this).data('idx', idx);
// Update the visual on the indexes in the list.
$('li').each(function(){
if(ui.item.index() !=$(this).index()){
$(this).data('idx',c++);
$(this).text(c);
}
})
c=0;
// CONSOLE RELATED (show indexes progression and gaps)
var info=$('.console').html();
if(oldInfo !=''){
var valAbs= Math.abs( parseInt(ui.item.text()) - parseInt(oldInfo));
if(valAbs==1){info=info+' + '+ui.item.text();}
else{info=info+' + <span style="color:red">'+ui.item.text()+'</span>';};
}
else{info=ui.item.text();};
$('.console').html(info);
oldInfo = ui.item.text();
}
});
旁注:
“更改”事件中的所有代码都是为您量身定制的,以便您查看问题,可能不是问题本身。我让你来评判它,但提这个才公平。
我在更改部分的实际脚本是不同的。它触发了某些表列的重新排序,这就是我第一次检测到问题的方式,因为表重新排序在高速下会出现故障。所以这里的虚拟脚本只是我将其缩小到最低限度,同时向您展示直观的方式。
关键是要评估它是否是可以解决的性能问题,是否缺少我应该添加的可排序选项,可以修复的拖动/光标延迟,或者是否有任何技巧可以以某种方式解决此跟踪问题。
我认为这是一个公平的警告,可以避免您调试一个只是展示的虚拟脚本的麻烦。但是考虑到我只是一个新手,我可能错了,请按您的意愿行事。
在任何情况下,我们都非常感谢您的帮助或意见。 提前谢谢你。
编辑:这是我真实的(缩小的)脚本,提供“dataTable.colReorder.move”事件。它涉及更多,因为它需要知道着陆索引(a/b)以及被拖动元素的当前索引(a/b/c/d)。并且 sortable 有自己的情境方式来索引它。
$( ".panel_list" ).sortable({
placeholder: 'panel_highlight',
items : '>li.ticked',
cancel : '>li.unticked',
start: function(event, ui){
lastValue='';
origValue=ui.item.index();
$(this).data('idx', ui.item.index());
},
change: function(event, ui){
var x;
var idx = ui.placeholder.prevAll().filter(':not(.ui-sortable-helper)').length;
var a= ui.placeholder.index();
var b=a+1;var c=a+2;var d=a-1;
if(idx - $(this).data('idx')==1)
{//downward
if((origValue>=a) || (x==1)){dataTable.colReorder.move(a,b);lastValue=b;x=0}
else {dataTable.colReorder.move(d,a);lastValue=a;}
}
else
{//upward
if(origValue>=a) {dataTable.colReorder.move(c,b);lastValue=b;x=1}
else {dataTable.colReorder.move(b,a);lastValue=a;}
}
$(this).data('idx', idx);
}
});
【问题讨论】:
-
这种快速变化是通过人工输入还是通过读取 API 结果完成的?这看起来很像足球联赛结果表
-
好老人类拖拉..
-
为什么有人想拖得这么快?你真的需要记录所有上下移动直到到达“停车”吗?还是单程(向上或向下)就足够了?
-
其实并不快。它相对较快。尝试使用四项列表,您将无法走得那么快。尝试列出 30 个项目,从一端到另一端,然后你就拥有了。您在两个坐标之间获得的空间越大,您获得的速度就越快。这是正常的。当像任何人一样使用系统时,有一个很长的列表,四分之一次,我处于亏损状态。所以,这根本不是一个假设的问题。而且那个速度真的没有超出范围。问题“列表越大,发生的频率越高,因为鼠标有更多的空间来获得速度”。
-
我昨天已经看过这个了,但是就像 Louys 一样想不出任何解决方案。因此我在之前的评论中提出了问题:你真的需要记录所有的上下移动吗?因为如果不是,我们可以计算所有移动,直到到达“停车”=您停下来的地方
标签: jquery performance jquery-ui jquery-ui-sortable onchange