向页面添加大量元素后出现的延迟问题

Issue with lag time after appending a large number of elements to the page

本文关键字:延迟 问题 元素 添加      更新时间:2023-09-26

我正在网格上实现虚拟滚动。滚动/按需加载功能工作相当顺利。但是,当检测到用户正在快速滚动(定义为超过450毫秒)时,在处理过程中显示一个带有加载gif的半透明div。

我的问题是,在加载完成和追加完成后,我调用隐藏覆盖期望看到更新的网格。相反,我有一个2-3秒的延迟,然后覆盖隐藏和数据显示。

问题:

Part A:为什么div没有留在屏幕上,即使隐藏它的代码行出现在附加的…导致意外的2-3秒等待,没有进度/加载指示给用户?

Part B:在完成添加和渲染之前,可以做些什么来确保覆盖保持可见?

执行行看起来像这样:

    CheckToFetch(id, $(gridScrollElm).scrollTop(), true);
    ToggleOverlay(gridScrollElm, false);

正如你所看到的,理想情况下,在数据加载和渲染后,覆盖应该隐藏。

CheckToFetch后面有一个方法调用链,但我只展示最相关的部分,其中发生追加。

AppendData: function (id, data, firstTime)
{
    var gd = SGrid.GetGridData(id);
    var rowClass = (gd["RecordCount"] + 1) % 2; //sets us on correct course for adding AlternatingRow classes
    var grid = $('#' + id)
    var tbody = grid.children('tbody');
    var rowsToAdd = data["Records"];
    for (var r = 0; r < rowsToAdd.length; r++)
    {
        var elmsQueue = new Array(); //used to do efficient string concat, especially for IE
        elmsQueue.push('<tr>');
        for (var c = 0; c < gd['Columns'].length; c++)
        {
            elmsQueue.push('<td align="');
            elmsQueue.push(gd['Columns'][c]['DataAlign']);
            elmsQueue.push('" ');
            var id = rowsToAdd[r]["id"];
            var cell = rowsToAdd[r]["cell"];
            if (rowClass % 2 == 0)
            {
                elmsQueue.push('class="AlternatingRow">');
            }
            else
            {
                elmsQueue.push('>');
            }
            elmsQueue.push(cell[c]);
            elmsQueue.push('</td>');
        }
        elmsQueue.push('</tr>');
        tbody.append(elmsQueue.join(''));
        rowClass++;
    }

关于你的问题 A部分,我只能假设,重绘操作(实际显示javascript操作结果的过程)可以独立于DOM操作和javascript执行运行。在你的代码中,你将多个元素附加到DOM中,DOM被更新,流流被发送给浏览器,但这(流流操作)并没有暂停javascript的执行。因此,如果回流持续了很长时间,即使你还没有看到上一条语句的结果,你最终还是会在执行下一个javascript函数。

有一些资源涉及绘制事件和dom操作性能:http://www.html5rocks.com/en/tutorials/speed/html5/(检查优化策略部分),以及来自独一无二的Paul Irish: http://paulirish.com/2011/viewing-chromes-paint-cycle/

关于你问题的 B部分如果我在A部分的假设是正确的,那么你唯一能做的就是确保重绘操作被限制在绝对最低限度。为了实现这一点,您应该暂停添加元素,直到您的完整集合准备好。换句话说,不断收集新的

数组(或字符串)中的元素,然后才执行tbody.append()。简单来说:将DOM操作移出循环

延迟实际的DOM修改这是一种常见的做法,并且推荐使用大量修改DOM的脚本。

为了获得性能的每一点,您也可以尝试传递实际对象(使用document.createElement创建)到append函数,而不是字符串,(显然)必须被解析,以便获得您想要放入DOM的元素列表。