【问题标题】:Need to loop through 500+ table rows and browser is choking需要遍历 500+ 表行并且浏览器阻塞
【发布时间】:2012-06-28 16:22:42
【问题描述】:

我有一个大表,其中列出了大约 50 个用户和一些关于他们帐户的简单数据,包括他们拥有的“项目”数量。单击用户行时,下方会展开更多行以显示有关其每个项目的详细信息。大多数用户的项目少于 20 个,因此对浏览器的负担并不大。但是,有一些用户拥有 100 多个项目(一个拥有 500 多个项目),当单击用户行时,浏览器会停顿 1-4 秒。

表行设置为默认隐藏任何具有.project 类的行,并且当单击用户行(无.project 类)时,所有具有.project 类的后续行都具有该类.open 添加显示它们。

关于如何使这个运行更快的建议?有没有更好、更清洁的方法来达到同样的效果?

这是 HTML 的简化版本:

<table>
    <tr>
        <td>Username</td><td>Email</td><td>10 Projects</td>
    </tr>
    <tr class="project">
        <td>&nbsp;</td><td>&nbsp;</td><td>Project Name</td>
    </tr>
    <tr class="project">
        <td>&nbsp;</td><td>&nbsp;</td><td>Project Name</td>
    </tr>
    <tr class="project">
        <td>&nbsp;</td><td>&nbsp;</td><td>Project Name</td>
    </tr>
    <tr class="project">
        <td>&nbsp;</td><td>&nbsp;</td><td>Project Name</td>
    </tr>
    <tr class="project">
        <td>&nbsp;</td><td>&nbsp;</td><td>Project Name</td>
    </tr>
    <tr class="project">
        <td>&nbsp;</td><td>&nbsp;</td><td>Project Name</td>
    </tr>
    <tr class="project">
        <td>&nbsp;</td><td>&nbsp;</td><td>Project Name</td>
    </tr>
    <tr class="project">
        <td>&nbsp;</td><td>&nbsp;</td><td>Project Name</td>
    </tr>
    <tr class="project">
        <td>&nbsp;</td><td>&nbsp;</td><td>Project Name</td>
    </tr>
    <tr class="project">
        <td>&nbsp;</td><td>&nbsp;</td><td>Project Name</td>
    </tr>
    <tr>
        <td>Username</td><td>Email</td><td>3 Projects</td>
    </tr>
    <tr class="project">
        <td>&nbsp;</td><td>&nbsp;</td><td>Project Name</td>
    </tr>
    <tr class="project">
        <td>&nbsp;</td><td>&nbsp;</td><td>Project Name</td>
    </tr>
    <tr class="project">
        <td>&nbsp;</td><td>&nbsp;</td><td>Project Name</td>
    </tr>
</table>

... 和 JS:

(function($) {

    $.fn.viewProjects = function() {

        this.each(function() {
            $(this).click(function(){

                var projects = $(this).nextUntil(':not(.project)'); // get all rows that follow and have the '.project' class

                if ($(this).hasClass('focused')) { // collapse
                    $(this).removeClass('focused');
                    projects.each(function(n, proj){
                        $(proj).removeClass('open');
                    });
                }
                else { // expand
                    $(this).addClass('focused');
                    projects.each(function(n, proj){
                        $(proj).addClass('open');
                    });
                }

            });
        });

    };

    $('tr:not(.project)').viewProjects();

})(jQuery);

【问题讨论】:

  • 您是否考虑过或愿意对结果进行分页?也就是说,在给定时间只显示 20 个用户项目..
  • 分页是另一种解决方案 - 好主意@happytimeharry

标签: jquery loops


【解决方案1】:

这是因为 DOM 正在向其中加载太多添加的内容。我在类似情况下的做法是:

  • 检查是否超过 50 行
  • 如果是这样,则在 50 处停止并放置“点击查看更多”链接。
  • 单击后,加载接下来的 50 行。
  • 继续此过程,直到加载所有行。

或者,您可以在用户向下滚动页面时自动触发加载接下来的 50 行。我更喜欢显示链接,因为自动加载内容可能会令人困惑。

编辑 - 如果你使用 jQuery 来显示和隐藏内容,而不是每次都添加和删除一个类怎么办?

if ($(this).hasClass('focused')) { // collapse
    $(this).removeClass('focused');
    projects.hide();
} 
else { // expand
    $(this).addClass('focused');
    projects.show();
}

【讨论】:

  • 隐藏也一样吗?例如,当单击具有 500 多个项目的用户时,显示这些项目大约需要 2 秒。再次单击以隐藏时,几乎需要同样长的时间。顺便说一句,我实际上并没有在 DOM 中添加或删除。我只是在更改一个将它们从position: absolute; 更改为position: static; 的类。
  • 听起来在绝对定位和静态定位之间切换非常占用处理器资源。我知道固定定位可能是处理器密集型的。你可以让你的元素保持绝对定位,然后在点击事件上在 jquery .show() 和 .hide() 之间切换吗?
【解决方案2】:

您可以检查webworker 来创建线程以提高性能。我知道这是一个模糊的,但我想建议这个方向。

不幸的是,我们无法在 webworkers 中操作 DOM。但是可以在您的客户端代码上操作 DOM。

您似乎正在发出 XMLhttprequest 来获取新数据,这可以在 webworkers 内部完成。

【讨论】:

    【解决方案3】:

    你不需要每个。 Jquery 中的点击功能是可链接的 这可能加快速度:

    (function($) {
    
        $.fn.viewProjects = function() {
    
                $(this).click(function(){
    
                    var projects = $(this).nextUntil(':not(.project)'); // get all rows that follow and have the '.project' class
    
                    if ($(this).hasClass('focused')) { // collapse
                        $(this).removeClass('focused');
                        projects.each(function(n, proj){
                            $(proj).removeClass('open');
                        });
                    }
                    else { // expand
                        $(this).addClass('focused');
                        projects.each(function(n, proj){
                            $(proj).addClass('open');
                        });
                    }
    
                });
    
        };
    
        $('tr:not(.project)').viewProjects();
    
    })(jQuery);
    

    【讨论】:

    • 有兴趣知道它是否有任何不同吗?
    【解决方案4】:

    不是显示/隐藏 500 项,而是显示/隐藏一项:

    将 HTML 重构为如下内容:

    <table>
        <tr>
            <td>Username</td><td>Email</td><td>10 Projects</td>
        </tr>
        <tr class="project">
            <td colspan="3">
                <ul>
                    <li>Project Name</li>
                    <li>Project Name</li>
                    <li>Project Name</li>
                    <li>Project Name</li>
                    <li>Project Name</li>
                    <li>Project Name</li>
                    <li>Project Name</li>
                    <li>Project Name</li>
                    <li>Project Name</li>
            </ul>
        </td>
    </tr>
    

    【讨论】:

    • 我考虑过,但项目细节需要与用户细节保持一致。
    • @BrandonDurham 不确定您所说的“项目细节需要与用户细节保持一致”是什么意思(视觉上?这肯定可以通过样式来完成)但是任何时候你有这样的 HTML:&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;是时候考虑重组了。
    • 那是简化的示例代码。我取出了敏感信息,换成了&amp;nbsp;
    猜你喜欢
    • 2012-01-02
    • 1970-01-01
    • 2018-07-16
    • 2015-05-14
    • 2016-08-16
    • 1970-01-01
    • 2018-12-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多