使用Javascript(或JQuery,如果它更快)是否有办法更快地对此进行排序?

时间:2015-03-10 15:38:11

标签: javascript jquery html sorting

我有一个html表,我用javascript排序。该表可以轻松拥有超过+1000行。

这是我目前所拥有的,html看起来与此类似:

<div id="mycollection" class="table">
    <div class="title">
        <div class="A">id</div>
        <div class="B">name</div>
        <div class="C">total</div>
        <div class="D">cost</div>
    </div>
    <div class="row">
        <div class="A">1</div>
        <div class="B">Jack</div>
        <div class="C">101</div>
        <div class="D">$5</div>
    </div>
    <div class="row">
        <div class="A">5</div>
        <div class="B">Zoe</div>
        <div class="C">5</div>
        <div class="D">$10</div>
    </div>
    <div class="row">
        <div class="A">3</div>
        <div class="B">Adam</div>
        <div class="C">21</div>
        <div class="D">$7</div>
    </div>
</div>

我的javascript看起来像这样:

function testSort(s) {
    var column = s;

    var parent = document.getElementById('mycollection');
    var rows = parent.children; // NodeList
    rows = Array.prototype.slice.call(rows, 0); // change NodeList to array
    var top = rows.shift(); // remove title row

    // sort
    rows.sort(function(a, b) {
        if(a.getElementsByClassName(column)[0].textContent < b.getElementsByClassName(column)[0].textContent) return -1;
        if(a.getElementsByClassName(column)[0].textContent > b.getElementsByClassName(column)[0].textContent) return 1;
        return 0;
    });

    // recreate div
    parent.innerHTML = ''; // clear
    parent.appendChild(top); // add title row
    for(var i=0, l=rows.length; i<l; i++) { // add rows
        parent.appendChild(rows[i]);
    }
}
testSort('D');

我在这里设置了一个jsfiddle:

http://jsfiddle.net/rotaercz/f6p377au/

*另外有没有办法让C和D列正确排序?它目前只按字母顺序排序。

2 个答案:

答案 0 :(得分:3)

作为一般规则,从{em>里面调用DOM访问或(!!)操作工具.sort()比较器功能是避免所有可能的努力。在这种情况下,您应该通过节点单次传递并提取文本内容一次。这将使你的排序更快,更快,特别是当行数超过几行时。

以下是如何执行此操作的示例:

function testSort(s) {
    var column = s;

    var parent = document.getElementById('mycollection');
    var rows = parent.children; // NodeList
    rows = Array.prototype.slice.call(rows, 0); // change NodeList to array
    var top = rows.shift(); // remove title row

    var extracted = rows.map(function(row) {
        return {
            text: row.getElementsByClassName(column)[0].textContent,
            row: row
        };
    });

    // sort
    extracted.sort(function(a, b) {
        if(a.text < b.text) return -1;
        if(a.text > b.text) return 1;
        return 0;
    });

    // recreate div
    parent.innerHTML = ''; // clear
    parent.appendChild(top); // add title row
    for(var i=0, l=extracted.length; i<l; i++) { // add rows
        parent.appendChild(extracted[i].row);
    }
}

在排序之前,该代码将rows数组转换为另一个数组,一个由普通对象组成。每个对象都有从列中提取的文本和一个返回DOM节点的引用。

sort函数因此可以直接引用字符串而无需调用.getElementsByClassName()

如果您有100行,那么可能会将几个百次次调用保存到.getElementsByClassName;对于1000行,它将节省数千个。

关于按内容的数值排序,您必须检测文本看起来是数字(按照您喜欢的任何标准)并隐式转换它,或者允许传递额外的参数表明应该这样做。我个人会去第二条路线,并改变功能签名:

function testSort(s, numeric) {

然后提取数组将以类似方式构建,但现在它被告知要转换为数字:

    var extracted = rows.map(function(row) {
        var sv = row.getElementsByClassName(column)[0].textContent;
        return {
            text: numeric ? +sv.replace(/\D/g, '') : sv,
            row: row
        };
    });

现在,当您传入数字标志时,排序比较器功能中的比较将正常工作:

testSort("D", true);

Link to the fixed version of your original jsfiddle.

答案 1 :(得分:0)

处理大量元素时的一个常见问题是不断重绘DOM。为了最大限度地减少这种情况并使其更快,您可以克隆您希望操作的DOM部分,进行更改然后进行替换,或者您可以创建表示元素的字符串并仅将结束字符串追加一次。

示例:

var urlsDOM             = '';
resultSet.forEach(function(result){
   urlsDOM += '<li>' + result.someProperty + '</li>';
});

同时检查此插件:TableSorter