在不破坏子列表的情况下对li元素进行排序



我正在尝试编写一些排序代码。我想将列表排序为:

  • 香蕉
  • 蛋糕
    • 鸡蛋
    • 甜甜圈
    • 汉堡包
  • 大米
  • 苹果

并转换为:

  • 苹果
  • 香蕉
  • 蛋糕
    • 鸡蛋
    • 甜甜圈
    • 汉堡包
  • 大米
<html>
<head>
<title>Sort list items alphabetically with Javascript</title>
<script type="text/javascript">
function sortUnorderedList(ul, sortDescending) {
if(typeof ul == "string")
ul = document.getElementById(ul);
var lis = ul.getElementsByTagName("LI");
var vals = [];
for(var i = 0, l = lis.length; i < l; i++)
vals.push(lis[i].innerHTML);
vals.sort();
if(sortDescending)
vals.reverse();
for(var i = 0, l = lis.length; i < l; i++)
lis[i].innerHTML = vals[i];
}
window.onload = function() {
var desc = false;
document.getElementById("test").onclick = function() {
sortUnorderedList("list", desc);
desc = !desc;
return false;
}
}
</script>
</head>
<body>
<input type="button" id="test" value="Sort List (click again to reverse)"/>
<ul id="list">
<li>banana</li>
<li>cake</li>
<ul>
<li>egg</li>
<li>doughnut</li>
<li>burger</li>
</ul>
<li>rice</li>
<li>apple</li>
</ul>
</body>
</html>

代码的主要问题是HTML无效;ul不能是另一个ul的子级。只有liol可以。这种无效的HTML会导致li的呈现方式与您预期的不同,因此排序会受到影响。要解决此问题,请更正HTML,使嵌套的"蛋糕"ul位于li中。

正如您已经用jQuery标记了这个问题一样,这里是您最初拥有的一个非常简单的实现:

jQuery($ => {
let $ul = $('#list');
$('#test').on('click', function() {
let sort = $(this).data('sortasc');
let dir = sort ? [1, -1] : [-1, 1];
$ul.children('li').sort((a, b) => a.innerText.trim() < b.innerText.trim() ? dir[0] : dir[1]).appendTo($ul);
$(this).data('sortasc', !sort);
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="test">Toggle sort</button>
<ul id="list">
<li>banana</li>
<li>
cake
<ul>
<li>egg</li>
<li>doughnut</li>
<li>burger</li>
</ul>
</li>
<li>rice</li>
<li>apple</li>
</ul>

最新更新