最简单的DOM节点排序方式?

时间:2008-11-12 00:58:45

标签: javascript dom

如果我有这样的清单:

<ul id="mylist">
    <li id="list-item1">text 1</li>
    <li id="list-item2">text 2</li>
    <li id="list-item3">text 3</li>
    <li id="list-item4">text 4</li>
</ul>

根据我的偏好重新安排DOM节点的最简单方法是什么? (这需要在页面加载时自动发生,列表顺序首选项从cookie获得)

E.g。

<ul id="mylist">
    <li id="list-item3">text 3</li>
    <li id="list-item4">text 4</li>
    <li id="list-item2">text 2</li>
    <li id="list-item1">text 1</li>
</ul>

9 个答案:

答案 0 :(得分:70)

虽然使用JS库可能有一种更简单的方法,但这是一个使用vanilla js的工作解决方案。

var list = document.getElementById('mylist');

var items = list.childNodes;
var itemsArr = [];
for (var i in items) {
    if (items[i].nodeType == 1) { // get rid of the whitespace text nodes
        itemsArr.push(items[i]);
    }
}

itemsArr.sort(function(a, b) {
  return a.innerHTML == b.innerHTML
          ? 0
          : (a.innerHTML > b.innerHTML ? 1 : -1);
});

for (i = 0; i < itemsArr.length; ++i) {
  list.appendChild(itemsArr[i]);
}

答案 1 :(得分:15)

您可能会发现对DOM节点进行排序效果不佳。一种不同的方法是在你的javascript中有一个数组,它表示将进入DOM节点的数据,对数据进行排序,然后重新生成保存DOM节点的div。

也许你没有那么多节点要排序,所以没关系。我的经验是基于尝试通过操纵DOM来对HTML表进行排序,包括包含数百行和几十列的表。

答案 2 :(得分:13)

查看实际操作:http://jsfiddle.net/stefek99/y7JyT/

    jQuery.fn.sortDomElements = (function() {
        return function(comparator) {
            return Array.prototype.sort.call(this, comparator).each(function(i) {
                  this.parentNode.appendChild(this);
            });
        };
    })();

<强>简洁

答案 3 :(得分:9)

我的版本,希望对其他人有用:

var p = document.getElementById('mylist');
Array.prototype.slice.call(p.children)
  .map(function (x) { return p.removeChild(x); })
  .sort(function (x, y) { return /* your sort logic, compare x and y here */; })
  .forEach(function (x) { p.appendChild(x); });

答案 4 :(得分:8)

如果您已经在使用jQuery,我建议使用tinysort:http://tinysort.sjeiti.com/

$("li").tsort({order:"asc"});
$("li").tsort({order:"desc"});

答案 5 :(得分:6)

使用es6语法来求助儿童:

var list = document.querySelector('#test-list')

[...list.children]
  .sort((a,b)=>a.innerText>b.innerText?1:-1)
  .map(node=>list.appendChild(node))

答案 6 :(得分:3)

这是一个ES6函数,用于对DOM节点进行排序:

const sortChildren = ({ container, childSelector, getScore }) => {
  const items = [...container.querySelectorAll(childSelector)];

  items
    .sort((a, b) => getScore(b) - getScore(a))
    .forEach(item => container.appendChild(item));
};

以下是如何使用它来对Untapped user reviews by score进行排序:

sortChildren({
  container: document.querySelector("#main-stream"),
  childSelector: ".item",
  getScore: item => {
    const rating = item.querySelector(".rating");
    if (!rating) return 0;
    const scoreString = [...rating.classList].find(c => /r\d+/.test(c));
    const score = parseInt(scoreString.slice(1));
    return score;
  }
});

答案 7 :(得分:1)

如果没有分析太多,如果这会给表带来任何新东西,我通常会使用它:

function forEach(ar, func){ if(ar){for(var i=ar.length; i--; ){ func(ar[i], i); }} }
function removeElement(node){ return node.parentNode.removeChild(node); }
function insertBefore(ref){ return function(node){ return ref.parentNode.insertBefore(node, ref); }; }

function sort(items, greater){ 
    var marker = insertBefore(items[0])(document.createElement("div")); //in case there is stuff before/after the sortees
    forEach(items, removeElement);
    items.sort(greater); 
    items.reverse(); //because the last will be first when reappending
    forEach(items, insertBefore(marker));
    removeElement(marker);
} 

其中item是同一父级的子数组。我们从最后一个开始删除,并从第一个开始追加,以避免在屏幕上可能出现的顶部闪烁。我通常得到这样的项目数组:

forEachSnapshot(document.evaluate(..., 6, null), function(n, i){ items[i] = n; });

答案 8 :(得分:0)

我能想到的最简洁的方法:

参数compare类似于Array.sort()中使用的比较函数。

排序子节点。

/**
 * @param {!Node} parent
 * @param {function(!Node, !Node):number} compare
 */
function sortChildNodes(parent, compare) {
  const moveNode = (newParent, node) => {
    // If node is already under a parent, append() removes it from the
    // original parent before appending it to the new parent.
    newParent.append(node);
    return newParent;
  };
  parent.append(Array.from(parent.childNodes) // Shallow copies of nodes.
                    .sort(compare) // Sort the shallow copies.
                    .reduce(moveNode, document.createDocumentFragment()));
}

排序子元素(子节点的子集)。

/**
 * @param {!Element} parent
 * @param {function(!Element, !Element):number} compare
 */
function sortChildren(parent, compare) {
  const moveElement = (newParent, element) => {
    // If element is already under a parent, append() removes it from the
    // original parent before appending it to the new parent.
    newParent.append(element);
    return newParent;
  };
  parent.append(Array.from(parent.children) // Shallow copies of elements.
                    .sort(compare) // Sort the shallow copies.
                    .reduce(moveElement, document.createDocumentFragment()));
}