小编典典

通过W3C DOM替换整个HTML文档还有哪些其他选择?

ajax

我很好奇人们在运行时在Ajax Web应用程序中替换 整个 文档的经历。很少见,但是我发现一些情况下,应用程序需要重建整个页面,并且 所有内容
都在本地存在而无需其他服务器往返。

我可以很容易地准备新的文档 或者 一个新的DOM树或字符串。因此,我正在评估各种方法的权衡。

如果我想使用String方法,这似乎可行:

document.open();
document.write(newStringDoc);
document.close();

大多数浏览器都可以正常运行,但是许多浏览器在重新渲染时都会出现轻微闪烁。我已经注意到,通过Firefox
4.0b7的第二次安装只会坐在那里旋转,就好像它正在加载一样。点击位置栏上的停止按钮似乎可以完成页面渲染。( 编辑:
此问题似乎已在4.0b8中修复)。此方法似乎还防止用户单击刷新来重新加载当前URL(它重新加载动态生成的页面)。

如果我使用新的DOM树方法(在灵活性和速度方面具有不同的优点/缺点),那么这似乎可行:

document.replaceChild(newDomDoc, document.documentElement);

大多数浏览器似乎都能很好地处理而不会闪烁。不幸的是,IE9 beta抛出“ DOM异常:HIERARCHY_REQUEST_ERR(3)”
replaceChild,但从未完成。我没有尝试使用最新的预览版来查看这是否只是一个已修复的新错误。( 编辑: 这似乎已在RC1中修复。)

我的问题是: 除了这两种方法之外,还有没有其他方法可以使用?是否有人在某些特定浏览器根本无法使用这些方法之一分解的情况下发出警告?

更新:
也许这会增加上下文并有助于想象。考虑一个应用程序离线的情况。没有可用于重定向或刷新的服务器。应用程序的必要状态已在客户端加载(或存储)。UI是从客户端模板构建的。

我相信Gmail使用嵌入在根文档中的iframe。看来,至少其中一些iframe的起始文档只是父文档然后处理的裸HTML5文档。

使用iframe是通过替换整个子iframe或仅替换其子文档来替换当前文档的要求的另一种变体。但是,将新文档附加到iframe的方法也存在相同的情况。


阅读 228

收藏
2020-07-26

共1个答案

小编典典

我想在总结研究过程时,将用自己的发现回答这个问题。

由于这两种方法之一都存在问题的两个浏览器均为beta版,因此我已经打开了错误报告,希望这些报告能够在其完整版本发布之前解决这些问题:

我也一直发现这个…

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 docs声称为“必需”的类型。

最后,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();
}

…假设您有能力像我一样选择方法。

2020-07-26