代码之家  ›  专栏  ›  技术社区  ›  James

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

  •  45
  • James  · 技术社区  · 16 年前

    如果我有这样一个列表:

    <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>
    

    <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>
    
    8 回复  |  直到 13 年前
        1
  •  85
  •   nickf    16 年前

    虽然使用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]);
    }
    
        2
  •  54
  •   Andreas buildpax    4 年前

    使用es6语法帮助儿童:

    var list = document.querySelector('#test-list');
    
    [...list.children]
      .sort((a,b)=>a.innerText>b.innerText?1:-1)
      .forEach(node=>list.appendChild(node));
    
        3
  •  23
  •   Corey Trager    16 年前

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

    也许你没有那么多的节点需要排序,所以这无关紧要。我的经验是尝试通过操作DOM对HTML表进行排序,包括具有数百行和几十列的表。

        4
  •  13
  •   Mars Robertson    12 年前

    在行动中看到它: 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);
                });
            };
        })();
    

    简短生硬的

        5
  •  10
  •   Ebrahim Byagowi    5 年前

    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); });
    
        6
  •  8
  •   Jay    13 年前

    http://tinysort.sjeiti.com/

    $("li").tsort({order:"asc"});
    $("li").tsort({order:"desc"});
    
        7
  •  7
  •   cgenco    7 年前

    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;
      }
    });
    
        8
  •  1
  •   peter    12 年前

    如果这给表格带来了新的内容,我通常会使用以下方法,而不会进行太多分析:

    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; });
    
        9
  •  0
  •   Leedehai    4 年前

    我能想到的最整洁的方式是:

    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()));
    }