代码之家  ›  专栏  ›  技术社区  ›  JW.

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

  •  19
  • JW.  · 技术社区  · 5 年前

    我很好奇人们更换 整个的 在Ajax web应用程序中的运行时文档。这很少见,但我发现有些情况下,应用程序需要重建整个页面 一切 在本地存在,而不需要另一个服务器往返。

    我可以很容易地准备新文件 任何一个 新的DOM树或字符串。所以我在评估各种方法的利弊。

    如果我想使用字符串方法,这似乎是可行的:

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

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

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

    document.replaceChild(newDomDoc, document.documentElement);
    

    大多数浏览器似乎处理得很好,没有闪烁。不幸的是,IE9 beta在 replaceChild 永远不会完成。我还没有尝试过最新的预览版本,看看这是否只是一个新的错误,得到了修复。( 编辑: 这在RC1中似乎是固定的。)

    我的问题是: 有没有人有不同的方法?有没有人有任何其他的注意事项,也许某个特定的浏览器在这些方法中的一个根本性的故障?

    更新: 也许这会增加语境,有助于想象。考虑应用程序脱机的情况。没有可重定向或刷新的服务器。应用程序的必要状态已在客户端加载(或存储)。用户界面是由客户端模板构建的。

    我相信Gmail使用嵌入在根文档中的iframe。看起来,这些iframe中至少有一部分的起始文档只是一个简单的HTML5文档,然后由父文档操作。

    使用iframe将是替换当前文档的另一个变体,替换整个子iframe或只是它的文档。在将新文档附加到iFrAME的过程中,存在着相同的情况。

    1 回复  |  直到 14 年前
        1
  •  19
  •   mckamey    14 年前

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

    由于这两个浏览器都是beta版,所以我打开了bug报告,希望能在完全发布之前解决这些问题:

    我也一直认为。。。

    document.replaceChild(newDomDoc, document.documentElement);
    

    …比这个快2-10倍。。。

    var doc = document.open("text/html");
    doc.write(newStringDoc);
    doc.close();
    

    …甚至包括构建DOM节点所需的时间与构建HTML字符串所需的时间。这可能是闪烁的原因,也可能只是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();
    }
    

    …假设你有能力选择你的方法 like I do .