【问题标题】:Sorting a list by data-attribute按数据属性对列表进行排序
【发布时间】:2021-05-24 00:28:18
【问题描述】:

我有一个按人名排序的职位列表,如下所示:

<ul>
  <li data-azsort="smithjohn">
    <a href="#">
      <span class="list-name">John Smith</span>
    </a>
    <span class="list-desc">Professor</span>
  </li>
  ..
  <li data-azsort="barnestom">
    <a href="#">
      <span class="list-name">Tom Barnes</span>
    </a>
    <span class="list-desc">Lecturer</span>
  </li>
</ul>

我已将data-azsort 属性添加到&lt;li&gt; 元素中,我想将这些列表元素弹出到一个数组中,并根据该data-* 属性进行排序(使用纯JavaScript)。

data-azsort (A-Z) 对列表进行排序并返回相同代码的最佳方法是什么?只有 JavaScript,没有 jQuery 等。

【问题讨论】:

  • 那么问题出在哪里? staff 是什么?
  • HTML 属性是data-sortaz 在您提到的data-azsort 的描述中。
  • 可以看到Element.getAttribute函数
  • @IvankaTodorova 谢谢,已更正
  • 应该只对一个列表有效还是对任意数量的列表有效?

标签: javascript html sorting html-lists


【解决方案1】:

这适用于任意数量的列表:它基本上收集 uls 中具有您的属性的所有 lis,根据它们的 data-* 属性值对它们进行排序并将它们重新附加到它们的父级。

Array.from(document.querySelectorAll("ul > li[data-azsort]"))
  .sort(({dataset: {azsort: a}}, {dataset: {azsort: b}}) => a.localeCompare(b)) // To reverse it, use `b.localeCompare(a)`.
  .forEach((item) => item.parentNode.appendChild(item));
<ul>
  <li data-azsort="skeetjon">
    <a href="#"><span class="list-name">Jon Skeet</span></a>
    <span class="list-desc">Stack Overflow user</span>
  </li>
  <li data-azsort="smithjohn">
    <a href="#"><span class="list-name">John Smith</span></a>
    <span class="list-desc">Professor</span>
  </li>
  <li data-azsort="barnestom">
    <a href="#"><span class="list-name">Tom Barnes</span></a>
    <span class="list-desc">Lecturer</span>
  </li>
</ul>
<ul>
  <li data-azsort="smithjohn">
    <a href="#"><span class="list-name">John Smith</span></a>
    <span class="list-desc">Professor</span>
  </li>
  <li data-azsort="barnestom">
    <a href="#"><span class="list-name">Tom Barnes</span></a>
    <span class="list-desc">Lecturer</span>
  </li>
  <li data-azsort="skeetjon">
    <a href="#"><span class="list-name">Jon Skeet</span></a>
    <span class="list-desc">Stack Overflow user</span>
  </li>
</ul>

有趣的是,它将所有lis 放在same 数组中,将它们全部排序,但最终找出li 最初属于哪个列表。这是一个非常简单直接的解决方案。

如果您想通过 numeric 数据属性对元素进行排序,请改用此排序功能:

// Presumably, the data-* attribute won’t be called `azsort`. Let’s call it `numsort`.
({dataset: {numsort: a}}, {dataset: {numsort: b}}) => Number(a) - Number(b) // `Number(b) - Number(a)` to reverse the sort.

稍长的 ECMAScript 5.1 替代方案是:

Array.prototype.slice.call(document.querySelectorAll("ul > li[data-azsort]")).sort(function(a, b) {
  a = a.getAttribute("data-azsort");
  b = b.getAttribute("data-azsort");

  return a.localeCompare(b);
}).forEach(function(node) {
  node.parentNode.appendChild(node);
});

【讨论】:

  • 非常好,完全按照我的要求做,而且代码很少。 +1
  • @Xufox 谢谢你的回答。我非常需要这个。但我需要它以相反的顺序和不同的数据属性,但没关系。也许在您的回答中告诉您要反转加载顺序是一个好主意,您只需将&lt; 设置为&gt;&gt; 设置为&lt;,结果为:return a &gt; b ? -1 : a &lt; b ? 1 : 0;
  • @purple11111 实际上,算了吧。更好的方法是a.localeCompare(b)。要反转它,您只需要在它前面加上一个-
【解决方案2】:

如何获取所有列表项,将它们推送到稍后将被排序的数组中?

var allListElements = document.getElementById("staff").getElementsByTagName("li");
var staff = new Array();
for (i = 0; i < allListElements.length; i++) {
  staff.push(allListElements[i].getAttribute('data-azsort'));
}

staff.sort(function(a, b) {
  if (a < b) return -1;
  if (a > b) return 1;
  return 0;
});

//Print

document.write('<h4>Sorted</h4>');
for (i = 0; i < staff.length; i++) { 
  document.write(staff[i] + "<br />");
}
<h4>Input</h4>

<ul id="staff">
  <li data-azsort="smithjohn">
    <a href="#">
      <span class="list-name">John Smith</span>
    </a>
    <span class="list-desc">Professor</span>

  </li>
  <li data-azsort="barnestom">
    <a href="#">
      <span class="list-name">Tom Barnes</span>
    </a>
    <span class="list-desc">Lecturer</span>

  </li>
</ul>

此外,您可以保存&lt;li&gt; 的索引并重新排序&lt;ul&gt;

【讨论】:

  • 是的,这会重新排序“数据”属性,但现在如何根据新排序再次输出完整列表?也就是带有标签、职位等
【解决方案3】:

您可以将比较函数传递给 Array.prototype.sort

你应该能够做类似的事情

$items = $('li[data-azsort]');
var compareElem = function (a, b) {
  if (a.attr('data-azsort') > b.attr('data-azsort') {
    return 1;
  } else {
   return -1
  }
};
Array.prototype.sort.apply($items, compareElem);

【讨论】:

  • 来自 OP:只有 JavaScript,没有 jQuery,等等。 或者你的代码中的 $ 不是 jQuery?
  • @Grundy 是的,那是 jQuery,但可以替换为 document.querySelectorAll。尽管如此,它在 sort 函数中缺少0 返回大小写(当两个名称相同时),并且它显然没有实际重新排序页面上的 HTML 节点。
  • @Xufox,是的,但作为回答,没有任何关于将 jQuery 替换为原生的东西 :-)
猜你喜欢
  • 1970-01-01
  • 2011-05-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多