JS基于子元素排序父元素

时间:2016-09-16 09:23:57

标签: javascript sorting dom

我想根据子值(span内容)对JavaScript div进行排序。

我在这里找到了一个关于javascript的排序算法: Easiest way to sort DOM nodes?

然而,这仅适用于简单列表。我希望有一个修改版本,不看段落元素。

HTML

  <div class="myclass">
    <p class="hide">1</p>
    <span>2</span>
  </div>

  <div class="myclass">
    <p class="hide">2</p>
    <span>1</span>
  </div>

  <div class="myclass">
    <p class="hide">3</p>
    <span>4</span>
  </div>

  <div class="myclass">
    <p class="hide">4</p>
    <span>1</span>
  </div>

JS

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

var items = list.childNodes;
var itemsArr = [];
for (var i in items) {
    // HERE I need to get to the SPAN Element but how?
    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]);
}

这是JSFiddle

2 个答案:

答案 0 :(得分:2)

这是一种可能的方法(demo):

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

var nodesToSort = list.querySelectorAll('.myclass');

Array.prototype.map.call(nodesToSort, function(node) {
  return {
    node: node,
    relevantText: node.querySelector('span').textContent
  };
}).sort(function(a, b) {
  return a.relevantText.localeCompare(b.relevantText);
}).forEach(function(item) {
  list.appendChild(item.node);
});

正如您所注意到的,这里有一些变化。

首先,正如我所说,您不需要使用root.childNodes,因为所有应该排序的项目都可以使用querySelectorAllgetElementsByClassname方法轻松收集(我选择前者,主要是出于一致性原因)。这也使基于nodeType的过滤变得多余。

(实际上,如果作者使用children属性代替childNodes,那么链接答案中也会多余,

其次,排序辅助数组现在不仅包含节点,还包含对象;此技术的目的 - 也称为memoization - 是为了最大限度地减少DOM查询的数量,从而提高性能。

(此处我已将innerHTML查询替换为textContent,因为您似乎只对此处的文字感兴趣,忽略了<span>中的任何内联标记。如果不是这种情况,只需将其替换回来)

最后,与原版的另一个变化:用简单的字符串函数替换双重比较(第一个==,然后是>) - localeCompare,专门用于比较字符串。

当然,现在整个过程的结构都是一系列操作:

  • 将项目数组与其记忆排序标准一起组织
  • 对此数组进行排序
  • (重新)将该数组中的节点附加到列表中

......不需要任何中间变量和东西。

目前尚不清楚结构是否统一(即,您是否总是希望根据<span>内容进行排序)。如果您只想根据可见文本进行排序,请考虑使用node.innerText代替node.querySelector('span').textContent。但请注意:innerText,虽然现代浏览器支持,但根据定义,它是一个缓慢的计算值。

答案 1 :(得分:0)

您可以使用flexboxes和CSS order:属性来更改其显示顺序,而不是更改文档顺序。