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);
答案 0 :(得分:1)
在我看来,片段被用作存储results_table的原始dom的一种方式。 for循环然后更改results_table。完成后,片段(包含原始表)将附加到results_table的末尾。
它基本上将新的搜索结果放在表格的顶部并将旧结果移到底部,因此片段和for循环都会做一些事情。
答案 1 :(得分:1)
此代码中文档片段的目的是暂时从DOM中删除表。
此方法仅对片段使用两个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
。