从顶层到底层对DOM节点数组进行排序

Sorting array of DOM nodes from top-level to bottom

本文关键字:数组 节点 排序 DOM      更新时间:2023-09-26

我有一个DOM节点的数组(javascript数组,而不是jQuery对象),它充当了处理它们的函数的队列。此数组可能包含具有父/子、祖父母/子等关系的元素。我总是希望先处理更高级的元素。我的第一个倾向是用javascript创建一个快速排序函数,但我知道如果我能使用javascript的原生Array.prototype.sort方法,它会更快。

我是这样尝试的:

domElements.sort(function (a, b) {
  return $(a).find(b).length ? 1 :
         $(b).find(a).length ? -1 :
         0;
});

但它似乎并不完美。我有时仍然会在他们的父母之前有孩子的成分。为什么不起作用?有没有一种方法可以用javascript的原生排序来实现这一点?

更新:在调查了答案中的方法后,我想知道它们的表现。以下是结果。请随意调整,看看性能如何适合您。

使用jQuery的unique方法可以节省一些时间:http://api.jquery.com/jQuery.unique/

jQuery.unique(domElements);

(因为你让我发布它。:-))

您已经说过您希望父元素在数组中的子元素之前,但您的代码

domElements.sort(function (a, b) {
  return $(a).find(b).length ? 1 :
         $(b).find(a).length ? -1 :
         0;
});

如果ab的父级,则返回1,这将使a在数组中比b晚。

所以我在想:

domElements.sort(function (a, b) {
  return $(a).find(b).length ? -1 :
         $(b).find(a).length ? 1 :
         0;
});

但是,检查一个元素是否是另一个元素的后代是如此直接,我想知道你是否真的需要allocate-a-jQuery-object-and-call-found:

domElements.sort(function (a, b) {
  return isParentOf(a, b) ? -1 :
         isParentOf(b, a) ? 1 :
         0;
});
function isParentOf(parent, elm) {
    while (elm) {
        elm = elm.parentNode;
        if (elm === parent) {
            return true;
        }
    }
    return false;
}

工作示例但请注意timmywil的回答—尽管它做了一些不必要的工作(当你关心的只是父母/孩子时,把兄弟姐妹排列好),但有一个预先准备好的jQuery函数!

看起来我混合了一个负号:

domElements.sort(function (a, b) {
  return $(a).find(b).length ? -1 :
         $(b).find(a).length ? 1 :
         0;
});

似乎有效。

根据源代码顺序对文档中的随机元素进行排序将将子节点和兄弟节点保持在适当的位置。

if(!Array.prototype.indexOf){
    Array.prototype.indexOf= function(what, i){
        if(typeof i!= 'number') i= 0;
        var L= this.length;
        while(i< L){
            if(this[i]=== what) return i;
            ++i;
        }
        return -1;
    }
}
function nodeSort(nodesArray, pa){
    pa= pa || document;
    var original= [], src= pa.getElementsByTagName('*'), L= src.length;
    for(var i= 0; i<L; i++){
        if(nodesArray.indexOf(src[i])!=-1) original.push(src[i]);
    }
    return nodesArray.sort(function(a, b){
        return original.indexOf(a)- original.indexOf(b);
    });
}