0

createDocumentFragment()在下面的代码中做了什么吗 ?

我正在尝试调整此代码。我不确定它是如何工作的,并且for循环似乎没有调用tableFrag. 你的见解?

function createTable(searchResults)
{
    var results_table = 
        document.getElementById("report_results").getElementsByTagName("table")[0];

    var newLink, tableFrag;
    tableFrag = document.createDocumentFragment();
    tableFrag.appendChild(results_table);

    for (result_index in searchResults.results)
    {
        newRow = results_table.getElementsByTagName("tbody")[0].insertRow(-1);

        newCell = newRow.insertCell(-1);
        newCell.appendChild(document.createTextNode(searchResults.results[result_index]["score"]));

        newCell = newRow.insertCell(-1);
        newLink = document.createElement("a");
        newLink.href = 
            "officer.php?officer_seq="+searchResults.results[result_index]["officer_seq"];
        newLink.appendChild(document.createTextNode(searchResults.results[result_index]["officer_id"]));
        newCell.appendChild(newLink);

        newRow = null;
    }
    document.getElementById("report_results").appendChild(tableFrag);
}

具体来说,让我感到困惑的是tableFrag在循环中找不到它:

    for (result_index in searchResults.results)
    {
        ...
        tableFrag this-or-that
        ...
    }
    document.getElementById("report_results").appendChild(tableFrag);
4

3 回答 3

1

这段代码中的文档片段的目的是暂时从 DOM 中删除表格。

  1. 将表从 DOM 移动到片段
  2. 对表执行操作
  3. 将表格从片段移回 DOM

这种方法只对片段使用两个 DOM 操作(步骤 1 和 3)。它使我们可以跳过步骤 2 所需的所有重新流程。

每个 DOM 操作操作(例如,在 DOM 内表中添加一行)都会导致页面重排(网络浏览器重新计算并重新绘制页面)。当顺序执行多个 DOM 操作操作(例如添加多行)时,无需在每次操作后进行重排。只有在整个过程之后,页面才应该重新流动。为了实现这一点,我们必须暂时将表从 DOM 中分离出来,方法是将其移动到片段中。脱离 DOM 的元素不会导致重新流动。

于 2012-11-30T21:29:32.597 回答
1

在我看来,该片段被用作存储 results_table 的原始 dom 的一种方式。然后 for 循环对 results_table 进行更改。完成后,片段(包含原始表)将附加到 results_table 的末尾。

它基本上是将新的搜索结果放在表格的顶部并将旧的结果移到底部,因此片段和 for 循环都可以做一些事情。

于 2012-11-30T21:08:13.027 回答
1

是的,它正在做一些事情:性能优化。

HTML 文档中的元素保存在树形数据结构中,您可以通过 DOM 接口(即类似document.getElementById(id)or的方法)访问它document.getElementsByClassName()。每次操作此树时,即当您通过 Javascript 代码插入、删除或修改节点时,浏览器的渲染引擎必须根据 CSS 定义的规则重新布局框(这也称为重排),并在浏览器窗口上重新绘制树的可见部分。

在您的情况下,您必须向表中添加固定数量的行。当循环开始时,您已经知道必须向N表中添加行。如果你只是简单地向 DOM 元素添加行,每次调用table.appendChild(row)浏览器都会测量、布局和绘制页面,这种情况在大多数情况下都会发生N(实际上浏览器会限制这些昂贵的操作,但任何规范都不需要这样做,所以我们可以出于学习目的假设每次追加时,浏览器都会使树无效并重新绘制)。

所有这些处理都是不需要的:我们不希望浏览器一次明显地增加表一行,我们只是想一次性将N行放入表中,一种事务DocumentFragment存在这个确切的目的:当您操作片段的子级时,浏览器不会测量和布局任何东西。这仅在您最终将片段附加到主 DOM 时才会发生。在我们想象的和简化的浏览器中,绘制例程只被调用一次,而不是N多次。

因此,您的脚本所做的是创建一个片段,从主 DOM 中删除表格,将节点添加到片段中,在表格附加到片段时对其进行操作,最后将整个片段添加回主 DOM,当孩子们最后测量、布置和涂漆。请注意,代码并没有明确地从 DOM 中删除表,但是Node.appendChild(node)当子节点已经属于某个层次结构时,这是该方法所做的:

将一个节点添加到指定父节点的子节点列表的末尾。如果节点已经存在,则将其从当前父节点中删除,然后添加到新的父节点。

DocumentFragment您可以在MDN上阅读更多信息。

于 2012-12-07T21:22:23.817 回答