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

mck*_*mey 20 html javascript ajax w3c dom

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

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

如果我想使用String方法,这似乎工作:

document.open();
document.write(newStringDoc);
document.close();
Run Code Online (Sandbox Code Playgroud)

大多数浏览器都做得很好,但很多浏览器在重新渲染时会有轻微的闪烁.我注意到,第二次通过Firefox 4.0b7只会坐在那里旋转,好像它正在加载.点击位置栏上的停止按钮似乎完成了页面渲染.(编辑:这似乎在4.0b8中修复)此外,此方法似乎阻止用户点击刷新以重新加载当前URL(它重新加载动态生成的页面).

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

document.replaceChild(newDomDoc, document.documentElement);
Run Code Online (Sandbox Code Playgroud)

大多数浏览器似乎完全没有闪烁处理这个.不幸的是,IE9 beta会抛出"DOM Exception:HIERARCHY_REQUEST_ERR(3)" replaceChild并且永远不会完成.我还没有尝试过最新的预览版本,看看这是否只是一个修复过的新bug.(编辑:这似乎是在RC1中修复的.)

我的问题:有没有人采用与其中任何一种不同的方法?有没有人有任何其他警告,或许某个浏览器从根本上打破了这些方法之一?

更新:也许这将增加背景并有助于想象力.考虑应用程序脱机的情况.没有可用于重定向或刷新的服务器.应用程序的必要状态已经加载(或存储)在客户端.UI由客户端模板构成.

我相信Gmail会使用嵌入在根文档中的iframe.看来,至少其中一些iframe的起始文档只是一个裸HTML5文档,然后父文档才会操作.

使用iframe将是替换当前文档的替代整个子iframe或仅替换其文档的另一种变体.虽然将新文档附加到iframe的方法存在同样的情况.

mck*_*mey 19

我想我会用自己的发现回答这个问题,因为我正在结束对此的研究.

由于这两种方法之一存在问题的两个浏览器都是测试版,我已经打开了错误报告,希望在完全发布之前解决这些问题:

我也非常一致地发现这......

document.replaceChild(newDomDoc, document.documentElement);
Run Code Online (Sandbox Code Playgroud)

......比这快2-10倍......

var doc = document.open("text/html");
doc.write(newStringDoc);
doc.close();
Run Code Online (Sandbox Code Playgroud)

...即使包括构建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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

人们可以覆盖所有基地并将它们组合起来......

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();
}
Run Code Online (Sandbox Code Playgroud)

......假设你有能力像我一样选择你的方法.

  • `newDoc.toDOM()`的实现在哪里? (2认同)
  • @Gili我4年后不得不刷新自己.`newDoc.toDom()`和`newDoc.toString()`是你在生成新文档时所做的一切.最后一个片段来自https://bitbucket.org/mckamey/duel/raw/tip/duel-js/target/duel.js (2认同)