for循环中使用的createDocumentFragment()

时间:2012-11-26 19:52:24

标签: ajax dom

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);

3 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分:1)

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

  1. 将表从DOM移动到片段
  2. 在表格上执行操作
  3. 将表格从片段移回DOM
  4. 此方法仅对片段使用两个DOM操作(步骤1和3)。它允许我们跳过步骤2所需的所有重新流程。

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

答案 2 :(得分:1)

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

HTML文档中的元素保存在tree data structure中,您可以通过DOM界面访问它(即document.getElementById(id)document.getElementsByClassName()等方法。每次操作此树时,即,当您通过Javascript代码插入,删除或修改节点时,浏览器的渲染引擎必须重新布局框(这也称为 reflow ),具体取决于规则用CSS定义,重绘浏览器窗口中树的可见部分。

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

所有这些处理都是不必要的:我们不希望浏览器一次一行地显示表格,我们只想在表格中放入N行,只需一次,一种交易DocumentFragment存在于此目的:当您操纵片段的子节点时,浏览器不会测量和布局任何内容。只有当您最终将片段附加到主DOM时才会发生这种情况。在我们想象和简化的浏览器中,绘制例程只调用一次,而不是N次。

所以你的脚本所做的就是创建一个片段,从主DOM中删除表,将节点添加到片段,在片段附加到片段时操作表,最后将整个片段添加回当孩子们最终被测量,布局和绘画时,主要的DOM。请注意,代码并没有明确地从DOM中删除表,但这是Node.appendChild(node)方法在子节点已经属于某个层次结构时所执行的操作:

  

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

您可以在MDN上详细了解DocumentFragment