使用JQuery对元素列表进行排序

11
我有一个使用jQuery获取的元素列表。
var $self = $(this);
var $fields = $('.identifier-controls', $self);

这个列表是需要在控件渲染时进行某种方式操作的元素列表。$fields中的每个元素包含一个名为"data-order"的数据属性。该属性告诉我应在控件中按照什么顺序排列这些元素(呃,要求)。顺序不必是直线顺序(也就是说第一个控件可以具有10的属性值,下一个可以是15,下一个可以是17等),只需按升序出现即可。有没有一种简单的方法可以实现这一点?我能想到的所有方法似乎都有点过于复杂。

4个回答

12

按照数据属性对jquery“类数组”对象进行排序的步骤:

  1. 通过jquery选择器选择所有对象
  2. 将其转换为实际的数组(而不是类数组的jquery对象)
  3. 对对象数组进行排序
  4. 使用dom对象数组将其转换回jquery对象

Html

<div class="item" data-order="2">2</div>
<div class="item" data-order="1">1</div>
<div class="item" data-order="4">4</div>
<div class="item" data-order="3">3</div>

普通的jquery选择器

$('.item');
[<div class="item" data-order="1">1</div>,
 <div class="item" data-order="2">2</div>,
 <div class="item" data-order="3">3</div>,
 <div class="item" data-order="4">4</div>
]

按照data-order的值进行排序

function getSorted(selector, attrName) {
    return $($(selector).toArray().sort(function(a, b){
        var aVal = parseInt(a.getAttribute(attrName)),
            bVal = parseInt(b.getAttribute(attrName));
        return aVal - bVal;
    }));
}
> getSorted('.item', 'data-order')
[<div class="item" data-order="1">1</div>,
 <div class="item" data-order="2">2</div>,
 <div class="item" data-order="3">3</div>,
 <div class="item" data-order="4">4</div>
]

看看getSorted()如何工作。

希望这有所帮助!


博客文章不见了 :-( - The Wanderer

8

试试这个:

$(function(){
   var $self = $(this);
   var sortedList = $('.identifier-controls', $self).sort(function(lhs, rhs){
      return parseInt($(lhs).attr("data-order"),10) - parseInt($(rhs).attr("data-order"),10);
   });
});

变量 sortedList 现在拥有排序后的元素。

@TheSheekGeek:请看我在其他答案中的注释,只要您知道您依赖于可能随时更改的未记录行为,并且您正在操纵jQuery存储元素的顺序,这将产生连锁反应,因为许多jQuery方法保证按特定顺序完成任务。(我也没有看到这如何在DOM中移动东西;那不是要求吗?) - T.J. Crowder
控件的另一部分中有代码处理将它们添加到DOM中的操作。控件实际上执行的操作是获取一堆已经存在的文本框和标签(只是li元素列表),并窃取它们,将它们重新添加到DOM中,从而生成一个看起来像带有所有文本框的下拉菜单的控件。需求之乐。(实际上并不那么糟糕) - The Sheek Geek

7

类似这样:

$fields.sort(function(a, b) {
    return a.getAttribute('data-order') > b.getAttribute('data-order');
}).appendTo($fields.parent());

Fiddle: http://jsfiddle.net/gCFzc/


1
jQuery对象不是数组,它们类似于数组。jQuery对象的sort函数未经记录,如果您查看jQuery.js文件,它们说它仅供内部使用。因此需要注意。话虽如此,如果您确定在打乱元素顺序时不会影响jQuery(我不确定),则可以手动应用Array.prototype.sort规范非常清楚,您应该能够在类似于数组的非数组对象上使用它。请注意,一旦排序完成,它们仍将显示在DOM中的相同位置。 - T.J. Crowder
@T.J.Crowder,jQuery 的开发者将其称为 sort 并使选择器结果类似于数组的设计决策是错误的。许多鸭子类型 JS 程序员会陷入这个陷阱中。 - soulcheck
它不再起作用了 - Martin Zvarík

3
一个插入排序可能是一个相当直接的方法。
或者有点颠覆性,您可以利用JavaScript引擎来实现:
var $fields, $container, sorted, index;

$container = $('body');
$fields = $("div[data-order]", $container);
sorted = [];
$fields.detach().each(function() {
    sorted[parseInt(this.getAttribute("data-order"), 10)] = this;
});
sorted.forEach(function(element) {
    $container.append(element);
});

现场示例:

(function($) {
    var $fields, $container, sorted, index;
  
    $container = $('body');
    $fields = $("div[data-order]", $container);
    sorted = [];
    $fields.detach().each(function() {
        sorted[parseInt(this.getAttribute("data-order"), 10)] = this;
    });
    sorted.forEach(function(element) {
        $container.append(element);
    });
})(jQuery);
<div data-order="30">30</div>
<div data-order="40">40</div>
<div data-order="10">10</div>
<div data-order="20">20</div>
<div data-order="1">1</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

以下是操作步骤:

  • 获取容器并从中获取字段。

  • 创建一个空数组。请记住,JavaScript 数组实际上并不是真正的数组,它们天生就是稀疏的。

  • 分离字段,然后循环遍历它们,从 DOM 元素中获取 data-order 并将 DOM 元素添加到该位置的数组中。这假定 data-order 值是唯一的。

  • 一旦我们有了原始 DOM 元素的数组,我们使用 forEach 循环遍历它们,并将它们附加到容器中。我没有使用 jQuery.each,因为 jQuery.each 甚至会调用不存在的数组索引的回调函数,如果您的 data-order 值非常稀疏,这可能会成为问题。 forEach 按数字顺序迭代条目,跳过不存在的条目。


1
谢谢,稍作修改后它对我有用。 - Obyno Pac

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接