Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/422.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 排序DOM节点的最简单方法?_Javascript_Dom - Fatal编程技术网

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

Javascript 排序DOM节点的最简单方法?,javascript,dom,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> forEachSna

如果我有这样一个列表:

<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>
forEachSnapshot(document.evaluate(..., 6, null), function(n, i){ items[i] = n; });
    文本1 文本2 文本3 文本4
根据我的喜好重新排列DOM节点的最简单方法是什么?(这需要在页面加载时自动发生,列表顺序首选项是从cookie中获得的)

例如

    文本3 文本4 文本2 文本1

虽然使用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]);
}
var list=document.getElementById('mylist');
var items=list.childNodes;
var itemsArr=[];
对于(项目中的var i){
如果(items[i].nodeType==1){//去掉空白文本节点
项目推送(项目[i]);
}
}
itemsArr.sort(函数(a,b){
返回a.innerHTML==b.innerHTML
? 0
:(a.innerHTML>b.innerHTML?1:-1);
});
对于(i=0;i
您可能会发现对DOM节点进行排序的效果不佳。另一种方法是在javascript中使用一个数组,该数组表示将进入DOM节点的数据,对该数据进行排序,然后重新生成保存DOM节点的div


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

如果您已经在使用jQuery,我建议tinysort:


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

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是同一父级的子级数组。我们删除了从最后一个开始的内容,并附加了从第一个开始的内容,以避免在屏幕的顶部出现闪烁。我通常会得到这样的项目数组:

<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>
forEachSnapshot(document.evaluate(..., 6, null), function(n, i){ items[i] = n; });
在行动中看到它:


简洁

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

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

下面是一个ES6函数,用于就地对DOM节点进行排序:

const-sortChildren=({container,childSelector,getScore})=>{
const items=[…container.querySelectorAll(childSelector)];
项目
.sort((a,b)=>getScore(b)-getScore(a))
.forEach(item=>container.appendChild(item));
};
以下是如何使用它进行排序:

sortChildren({
容器:document.querySelector(#main stream”),
子选择器:“.item”,
getScore:item=>{
const rating=item.querySelector(“.rating”);
如果(!rating)返回0;
const scoreString=[…rating.classList].find(c=>/r\d+/.test(c));
const score=parseInt(scoreString.slice(1));
返回分数;
}
});

使用es6语法帮助儿童:

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

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

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

param
compare
与中使用的比较函数类似

对子节点进行排序

/**
*@param{!Node}父级
*@param{function(!Node,!Node):number}比较
*/
函数sortChildNodes(父级,比较){
const moveNode=(newParent,node)=>{
//如果节点已经在父节点下,则append()会将其从
//将原始父级添加到新父级之前。
newParent.append(节点);
返回新父母;
};
parent.append(Array.from(parent.childNodes)//节点的浅拷贝。
.sort(compare)//对浅拷贝进行排序。
.reduce(moveNode,document.createDocumentFragment());
}
对子元素(子节点的子集)进行排序

/**
*@param{!Element}父级
*@param{function(!Element,!Element):number}比较
*/
函数sortChildren(父级,比较){
常量moveElement=(新父元素,元素)=>{
//如果元素已经在父元素下,则append()会将其从
//将原始父级添加到新父级之前。
newParent.append(元素);
返回新父母;
};
parent.append(Array.from(parent.children)//元素的浅拷贝。
.sort(compare)//对浅拷贝进行排序。
.reduce(moveElement,document.createDocumentFragment());
}

我不确定这是否对您有帮助,但如果您在此页面上使用服务器端技术(如PHP),那么它也应该可以访问cookies。在PHP中,它位于全局$\u COOKIE数组中。感谢您的解决方案NickF,我将对它进行一些调整,因为我使用的是jQuery,但我想我现在知道了如何做,谢谢!)通过使用
list.childrends
而不是
list.childNodes
,您可以避免检查文本节点。当我第一次阅读此答案时,我想是什么?为什么这里需要?:^)@LivingstonSamuel…但是以不在IE工作为代价(甚至是IE11!)很好!我也喜欢简洁的东西,因此基于此,我提出了一个函数,它允许您提供一个回调函数来计算要排序的值。(我举了两个例子:按字母顺序对列表进行排序,以及按第一列中的数字值对表进行排序——基本上都是一行。)我知道这是一篇老文章,但我想问一下,使用自执行函数返回SortDomellements函数有什么好处?说jQuery.fn.sortdomements=function(comparitor)不是更简洁吗?与此类似,Tinysort的速度比13行代码慢数倍,这是基于对jquery选择结果进行排序并将其追加到后面的结果——Tinysort曾经是一个jquery插件,但被重写以删除jquery依赖项。它现在变小了,变快了。你说的排序逻辑是什么意思代码看起来不错,但是我的排序逻辑有点弱,这意味着你应该把排序逻辑放在那里,看看基本上是一样的,只有x和y是DOM节点。很好!这是一个干净的方法。太棒了!这是最聪明的重新订购方式
var list = document.querySelector('#test-list');

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