【问题标题】:Quick HTML Table Sorting?快速 HTML 表格排序?
【发布时间】:2012-07-03 12:08:27
【问题描述】:

是的,我知道有很多 JS/jQuery 程序可以做到这一点。我目前正在使用 http://www.kryogenix.org/code/browser/sorttable/sorttable.js 。这很简单:只需一个 JS 文件,向您的表中添加一些类属性,然后就可以了。特别是,您实际上不需要了解 JS 即可使用它,并且您可以添加自定义排序键,而无需编写自己的 JS 来扩展它。由于这两个原因,我非常喜欢它。主要问题:我的表大约 9300 行长,排序需要 10-20 秒。所以我想知道,还有比这更快的脚本吗?这些是我找到的:

http://webfx.eae.net/dhtml/sortabletable/sortabletable.html(甚至不知道这是什么用途)
http://tablesorter.com/docs/(真的很好,但不容易扩展,需要了解 JS/jQuery) http://flexigrid.info/(矫枉过正,我只需要一个表格排序器,而不是整个数据操作程序)
http://datatables.net/(矫枉过正,需要 Js/jQuery 扩展)

我确信还有 5000 个其他程序可以做我想做的事,但我没有时间弄清楚并测试它们是否都快。因此,我想知道是否有人在 StackOverflow 上可以向我指出他们知道哪个库很快,所以我只需要弄清楚如何使用一个程序。

(顺便说一句,我已经看到 Java 使用快速排序在毫秒内对数十万个数字进行排序;有人知道 JS.sort() 使用什么算法吗?)

【问题讨论】:

  • 你用 jquery 标记了这个,但听起来你想避免这种依赖......它是哪种方式?
  • 当然,java 可以快速地对 数字 进行排序,但是您正在对 DOM 进行排序。 DOM 操作很慢。您的问题从 HTML 表中的 9300 行开始。我会在服务器端对其进行排序。但如果你不想这样做,也许将数据存储在 JS 对象中,每次排序和重新渲染表格会更快。
  • @Robert:是的,我想避免它,但如果有必要,我会采取任何快速的方法并学习 JQuery。
  • @Christian:我确实提供了按一列排序的 HTML,但是从许多不同的列中排序的数据很有趣。我目前使用的 JS 读取 HTML,将条目存储在数组中,然后在数组上使用 JS 的内置 sort()。

标签: javascript jquery performance sorting html-table


【解决方案1】:

我在 DataTables(另一个 jQuery 插件)方面取得了巨大成功,其行号与您所说的相似。与在 java 中看到的相比,您使用 javascript 看到的速度损失实际上是在渲染 DOM,这需要更多的工作。 DataTables 的美妙之处在于您能够从 javascript 数组(本质上是 json)中获取数据 - 所以排序是在数组上完成的(与 java 的速度相似),然后只需要用户查看表的一部分在 DOM 中生成。

请参阅以下网址以获取示例:

http://datatables.net/examples/data_sources/js_array.html

http://datatables.net/examples/data_sources/ajax.html

我建议使用后者。如果使用静态 json 数组仍然不够快,您将需要构建一个服务器端脚本来减轻 javascript 的负载 - 这里是服务器端代码的一个很好的例子:

http://datatables.net/examples/data_sources/server_side.html

编辑:无限滚动

正如 cmets 中所讨论的,问题不在于排序,而在于将 HTML 表格转换为 JS 并返回。这可能有助于在用户查看时仅加载返回排序的渲染部分;服务器还以 JSON 形式向 JS 提供与表格相同的信息。这两种技术消除了 HTML-JS 的转换和渲染问题,从而大大提高了速度。

HTML(这是在 JSON 出现之前最初必须呈现的所有内容 - 添加与列一样多的标签):

<table id="table_id">
    <thead>
        <tr>
            <th>Column 1</th>
            <th>Column 2</th>
            <th>etc</th>
        </tr>
    </thead>
    <tbody>
    </tbody>
</table>

查询:

$(document).ready(function() {
    $('#table_id').dataTable( {
        "bScrollInfinite": true,
        "bScrollCollapse": true,
        "sScrollY": "200px",
        "bProcessing": true,
        "sAjaxSource": 'array.txt'
    });
});

array.txt 包含:

{ "aaData": [
    ["This will be in column 1","This in two","this in 3"],
    ["another row - column 1","another two","another 3"]
]}

【讨论】:

  • 所以你的意思是排序不是难的部分,而是将 9300 行 HTML 转换成一个数组需要这么长时间?这就是第一个链接的序言似乎也说的。在那种情况下,我只修改我已经使用的简单 JS 使其不进行自己的解析不是更容易吗?编辑:克里斯蒂安·瓦尔加也是这么说的,不是吗?
  • 浏览器在你执行任何 javascript 之前就渲染了数千行的 DOM,这需要很长时间——然后将其转换为数组会进一步减慢它的速度。如果您首先提供数组中的数据、排序,然后只要求浏览器呈现您需要的行,您应该会看到速度大幅提升。
  • 是的,实际上是浏览器的渲染耗时最长,请查看这个 jsFiddle:jsfiddle.net/wkndw。在我的机器上,数字在 300 毫秒内生成、排序并附加到 dom(根据分析器),但实际渲染它需要更长的时间 - 以秒为单位。
  • 那么你是对的 - 从 DOM 构建数组效率低下,也许还有排序功能。我没有查看数据表的内容以了解它们是如何处理排序的,但是我已经在超过 10,000 行的表上实现了动态排序,并且它在除旧版本 IE 之外的所有内容上都表现良好。我会试一试,您所要做的就是将您的表格转换为 JSON 数组并将其保存为文本文件。理想情况下,使用服务器端来消除 js 的压力。如果用户重新排序,只需调用服务器端脚本以新顺序返回 json
  • 问题可能是您选择的插件在执行排序后当前用于呈现表格的方法。此方法可能更适合您:datatables.net/release-datatables/examples/basic_init/… - 逐位呈现数据后排序 - 否则您唯一的选择是服务器端。
【解决方案2】:

除了库之外,表格排序很容易自己完成。

与 DOM 移动项目所需的时间相比,实际对行进行排序所花费的时间可以忽略不计。

将为您提供最佳性能的一件事是分离行,根据您的需要排列它们,然后重新附加它们。您不需要原始 JSON 数据,只需分离 $tr,从 td 中获取您要比较的值,创建一个 $tr 数组,根据您想要的列对该数组进行排序并将它们附加回您的 tbody。

例如,使用这种技术,我可以在 1 秒内对 15 列的 3000 行进行排序,这是完全可行的。有了这样的性能,唯一的问题是如何将 3000 行获取到浏览器...

【讨论】:

    【解决方案3】:

    我知道这篇文章有点老了,但这是对我来说非常有用的 ES6+ 解决方案。

    /**
     * Sort table data based on a direction of asc or desc for a specific column
     * @param {number} n- column number calling this sort
     * @param {string} dir -direction of the sort (asc or desc)
     * @param {HTMLSpanElement} targetElem -sort icon
     */
    function sortTable(n, dir = "asc", targetElem) {
        targetElem.style.cursor = "progress";       
        let sortArr = [];
        let table =targetElem.closest('table');
        table.querySelectorAll('tbody > tr > td:nth-Child(' + parseInt(n) + ')').forEach((x, y) => sortArr.push(
            {
                sortText: x.innerHTML.toLowerCase(),
                rowElement: x.closest('tr')
            }));
        var sorted = sortArr.sort(function (a, b) {
            if (dir == "asc") {
                if (a.sortText < b.sortText) {
                    return -1;
                }
            } else if (dir == "desc") {
                if (a.sortText > b.sortText) {
                    return -1;
                }
            }
            return 0;
        });
        sorted.forEach((x, y) => {
            x.rowElement.parentNode.insertBefore(x.rowElement, x.rowElement.parentNode.children[y]);
        });
        targetElem.style.cursor = null;
    }
    

    在我的每个 th 元素中,我都有用于调用此函数的排序图标。它们的列号嵌入在数据标签中。 它们看起来像:

    <th data-field-name="lastLogin" role="columnheader" class="lastLogin">Last Login
        <span class="fa fa-unsorted sort-icon" title="Sort Descending" data-col-number="6" style="font-size: 1.2em; margin-left: 15px;"></span>
    </th>
    

    图标的点击动作:

    click(icon){
            var parent = icon.closest('tr');
            parent.querySelectorAll('.sort-icon').forEach(x => {
                if (x == icon) {
                    return;
                }
                delete x.dataset.dir;
                x.classList.replace('fa-sort-down', 'fa-unsorted');
                x.classList.replace('fa-sort-up', 'fa-unsorted');
            });
    
            if (icon.classList.contains('fa-unsorted')) {
                icon.classList.replace('fa-unsorted', 'fa-sort-up');
                icon.title = icon.title.replace('Ascending', 'Descending');
                icon.dataset.dir = "asc";
            } else if (icon.classList.contains('fa-sort-down')) {
                icon.classList.replace('fa-sort-down', 'fa-sort-up');
                icon.dataset.dir = "asc";
                icon.title = icon.title.replace('Ascending', 'Descending');
            } else if (icon.classList.contains('fa-sort-up')) {
                icon.classList.replace('fa-sort-up', 'fa-sort-down');
                icon.title = icon.title.replace('Descending', 'Ascending');
                icon.dataset.dir = "desc";
            }
            sortTable(icon.dataset.colNumber, icon.dataset.dir, icon);
    }
    

    【讨论】:

      【解决方案4】:

      我认为这个 javascript 库简单而强大: http://tabulator.info

      Tabulator 允许您在几秒钟内从任何 HTML 表格、JavaScript 数组、AJAX 数据源或 JSON 格式的数据创建交互式表格。

      您可以在单元格内放置文本、进度条、图像、其他表格!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-08-14
        • 2016-12-23
        • 1970-01-01
        • 1970-01-01
        • 2021-07-14
        • 2012-03-14
        • 2014-10-10
        相关资源
        最近更新 更多