我对人们在运行时在Ajax web应用程序中替换整个文档的体验感到好奇。这种情况很少见,但我发现在一些情况下,应用程序需要重新构建整个页面,并且所有内容都显示在本地,而不需要另一个服务器往返。
我可以轻松地将新文档准备为新的DOM树或字符串。因此,我正在评估各种方法的权衡。
如果我想使用字符串方法,这似乎是可行的:
document.open();
document.write(newStringDoc);
document.close();
大多数浏览器都能很好地做到这一点,但许多浏览器在重新渲染时会有轻微的闪烁。我注意到,在第二次通过Firefox4.0b7将只是坐在那里旋转,就像它是加载的。点击地址栏上的停止按钮似乎可以完成页面渲染。( current:这似乎在4.0b8中得到了修复)此外,这个方法似乎阻止用户点击刷新来重新加载当前的(它重新加载动态生成的页面)。
如果我使用一种新的DOM树方法(它在灵活性和速度上有不同的优点/缺点),那么这似乎是可行的:
document.replaceChild(newDomDoc, document.documentElement);
大多数浏览器似乎都能很好地处理这个问题,而不会出现闪烁。不幸的是,IE9测试版在replaceChild
上抛出了"DOM Exception: HIERARCHY_REQUEST_ERR (3)“,并且永远不会完成。我还没有试过最新的预览版,看看这是不是一个新的bug已经修复了。(编辑:此问题似乎已在RC1中修复。)
我的问题:,有谁有比这两种方法都不同的方法吗?有没有人有任何其他的警告,也许某个特定的浏览器会因为这些方法中的一种而从根本上崩溃?
更新:也许这会增加背景,帮助想象。考虑一个应用程序离线的情况。没有服务器可用于重定向或刷新。应用程序的必要状态已经加载(或存储)客户端。UI是从客户端模板构建的。
我相信Gmail使用嵌入在根文档中的iframe。这些iframe中至少有一部分的起始文档似乎只是一个空的HTML5文档,然后父文档会对其进行操作。
使用iframe将是通过替换整个子iframe或仅替换其文档来替换当前文档的要求的另一个变体。但是,对于将新文档附加到iframe的方法,也存在相同的情况。
发布于 2010-12-02 05:22:02
我想我会用我自己的发现来回答这个问题,因为我正在结束我的研究。
由于这两种浏览器的其中一种方法都有问题,所以我已经打开了bug报告,希望能在完全发布之前解决这些问题:
编辑: FF 4b8中固定的。
编辑:已在IE9 RC1中修复。
我也一直发现这一点...
document.replaceChild(newDomDoc, document.documentElement);
...is比这个快2-10倍...
var doc = document.open("text/html");
doc.write(newStringDoc);
doc.close();
当包含构建DOM节点所需的时间与构建...even字符串的时间时。这可能是闪烁的原因,也可能只是DOM方法的另一个支持论点。Chrome在这两种方法中都没有任何闪烁。
请注意,存储返回的document
的细微变化绕过了Firefox4.0b7中的错误。
还要注意这个添加的MIME类型,IE文档声称它是“必需的”。
最后,Internet Explorer在解析在换入新文档之前构建的链接标记时似乎遇到了一些麻烦。将链接href分配回自身似乎可以修补它。
// IE requires link repair
if (document.createStyleSheet) {
var head = document.documentElement.firstChild;
while (head && (head.tagName||"") !== "HEAD") {
head = head.nextSibling;
}
if (head) {
var link = head.firstChild;
while (link) {
if ((link.tagName||"") === "LINK") {
link.href = link.href;
}
link = link.nextSibling;
}
}
}
一个人可以覆盖所有的碱基,并像这样将它们结合起来。
var doc = document;
try {
var newRoot = newDoc.toDOM();
doc.replaceChild(newRoot, doc.documentElement);
// IE requires link repair
if (doc.createStyleSheet) {
var head = newRoot.firstChild;
while (head && (head.tagName||"") !== "HEAD") {
head = head.nextSibling;
}
if (head) {
var link = head.firstChild;
while (link) {
if ((link.tagName||"") === "LINK") {
link.href = link.href;
}
link = link.nextSibling;
}
}
}
} catch (ex) {
doc = doc.open("text/html");
doc.write(newDoc.toString());
doc.close();
}
...assuming你有能力选择你的方法like I do。
https://stackoverflow.com/questions/4297877
复制相似问题