我很好奇人们在运行时在 Ajax 网络应用程序中替换整个文档的体验。这种情况很少见,但我发现在一些情况下应用程序需要重建整个页面并且一切都在本地存在而不需要另一个服务器往返。
我可以轻松地将新文档准备为 新的 DOM 树或字符串。因此,我正在评估各种方法的权衡。
如果我想使用 String 方法,这似乎可行:
document.open();
document.write(newStringDoc);
document.close();
大多数浏览器都能很好地做到这一点,但许多浏览器在重新呈现时会出现轻微的闪烁。我注意到,在第二次通过 Firefox 4.0b7 时,它只会坐在那里旋转,就好像它正在加载一样。点击地址栏上的停止按钮似乎可以完成页面呈现。 (编辑:这似乎已在 4.0b8 中修复)此外,此方法似乎可以防止用户点击刷新以重新加载当前 URL(它会重新加载动态生成的页面)。
如果我使用新的 DOM 树方法(在灵 active 和速度方面具有不同的优势/劣势),那么这似乎可行:
document.replaceChild(newDomDoc, document.documentElement);
大多数浏览器似乎都可以很好地处理这个问题而不会出现闪烁。不幸的是,IE9 beta 在 replaceChild
上抛出“DOM 异常:HIERARCHY_REQUEST_ERR (3)”并且永远不会完成。我还没有尝试最新的预览版来查看这是否只是一个已修复的新错误。 (编辑:这似乎已在 RC1 中修复。)
我的问题:有没有人有不同于这两种方法的方法?有没有人有任何其他警告,其中可能特定浏览器从根本上崩溃了这些方法之一?
更新:也许这会增加上下文并帮助想象。考虑应用程序离线的情况。没有可用于重定向或刷新的服务器。应用程序的必要状态已经加载(或存储)在客户端。 UI 由客户端模板构建。
我相信 Gmail 使用嵌入在根文档中的 iframe。看起来至少其中一些 iframe 的起始文档只是一个裸 HTML5 文档,然后父文档对其进行操作。
使用 iframe 是通过替换整个子 iframe 或仅替换其文档来替换当前文档的要求的另一种变体。将新文档附加到 iframe 的方法也存在相同的情况。
最佳答案
我想我会在结束对此的研究时用我自己的发现来回答这个问题。
由于其中一种方法有问题的两个浏览器都是测试版,我已经打开了错误报告,希望能在它们完全发布之前解决这些问题:
- Firefox 4 测试版:https://bugzilla.mozilla.org/show_bug.cgi?id=615927
编辑:在 FF 4b8 中修复。 - Internet Explorer 9 测试版:https://connect.microsoft.com/IE/feedback/details/626473
编辑:在 IE9 RC1 中修复。
我也一直发现这...
document.replaceChild(newDomDoc, document.documentElement);
...比这快 2-10 倍...
var doc = document.open("text/html");
doc.write(newStringDoc);
doc.close();
...即使包括构建 DOM 节点与构建 HTML 字符串所需的时间。这可能是闪烁的原因,或者可能只是 DOM 方法的另一个支持论点。 Chrome 在这两种方法中都没有任何闪烁。
请注意存储返回的 document
的细微变化,这避免了 Firefox 4.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();
}
...假设您有能力选择您的方法like I do .
关于javascript - 通过 W3C DOM 替换整个 HTML 文档还有哪些其他选项?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4297877/