【问题标题】:What other options for replacing entire HTML document via W3C DOM?通过 W3C DOM 替换整个 HTML 文档还有哪些其他选项?
【发布时间】:2011-05-16 22:06:21
【问题描述】:

我很好奇人们在 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 在replaceChild 上抛出“DOM Exception: HIERARCHY_REQUEST_ERR (3)”并且永远不会完成。我还没有尝试过最新的预览版本,看看这是否只是一个已修复的新错误。 (编辑:这似乎已在 RC1 中修复。)

我的问题:是否有人有与这两种方法不同的方法?是否有人有任何其他警告,可能某个特定浏览器从根本上因这些方法之一而崩溃?

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

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

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

【问题讨论】:

  • “我发现应用程序需要重新构建整个页面的一些情况” - 这绝不应该必需,这可能意味着您需要重新设计您的应用程序。可以修改页面上的几乎所有内容,而无需实际替换文档本身。
  • 恕我直言,这不是您的电话。有时您需要构建一个全新的文档。例如,Gmail 就是这样做的。
  • 如果您需要重建整个文档,为什么不使用浏览器多年来专门为此目的而设计的功能:重新加载页面?
  • @McKAMEY:我不知道 Gmail 是否以及何时这样做,但这并不正确。如果你真的需要构建一个新文档,那么它本质上是一个不同的应用程序,那么为什么不直接加载一个不同的页面呢?
  • 页面是从客户端状态动态构建的。如果人们坚持这个问题而不是质疑这种方法的推理,我将不胜感激。一旦我对这种方法进行了所有权衡,那么我将评估它是否是我想要采取的路径。我不需要帮助进行评估。

标签: javascript html ajax dom w3c


【解决方案1】:

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

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

我也始终如一地发现这...

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

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-05-14
  • 2015-11-20
  • 1970-01-01
  • 1970-01-01
  • 2013-08-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多