还有什么其他选项可以通过W3C DOM替换整个HTML文档? [英] What other options for replacing entire HTML document via W3C DOM?

查看:105
本文介绍了还有什么其他选项可以通过W3C DOM替换整个HTML文档?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



我可以轻松地将新文档准备为 一个新的DOM树或一个String。所以我正在评估各种方法的权衡。



如果我想使用String方法,这似乎是有效的:

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

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



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

  document.replaceChild(newDomDoc,document.documentElement); 

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



我的问题:有没有人有其他方法比任何一个?有没有人有任何其他注意事项,也许特定的浏览器根本上会以这些方法之一发生故障?



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



我相信Gmail使用嵌入在根文档中的iframe。这些iframe中的至少一些的起始文档似乎只是一个裸文件,然后父文档就可以操作。



使用iframe将是另一个变体替换当前的文档,替换整个child iframe或者只是它的文档。同样的情况存在,虽然新的文档附加到iframe的方法。

解决方案

我想我会用我的自己的发现,因为我正在包装我的研究这个。



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





我也很一致地发现这个...

  DOCUME nt.replaceChild(newDomDoc,document.documentElement); 

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

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

...即使包含构建DOM节点所需的时间,也不建立HTML字符串。这可能是闪烁的原因,或者也许是DOM方法的另一个支持性论据。 Chrome不会有任何闪烁的方法。



请注意,存储返回的文档的细微变化规避Firefox 4.0b7中的错误。



另请注意,IE文档声明的添加的MIME类型为必需。



最后,Internet Explorer似乎在解决在新文档被替换之前构建的链接标签有一些麻烦。将链接href分配回本身似乎可以修补。

  // IE需要链接修复
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; 
尝试{
var newRoot = newDoc.toDOM();
doc.replaceChild(newRoot,doc.documentElement);

// IE需要链接修复
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();
}

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


I am curious about people's experiences with replacing the entire document at runtime in an Ajax web app. It's rare, but I've found a few situations where the app requires an entire page rebuild and everything is present locally without needing another server round-trip.

I can easily prepare the new document as either a new DOM tree or as a String. So I'm evaluating the trade-offs for various approaches.

If I want to use the String approach this seems to work:

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

Most browsers do this just fine, but many have a slight flicker when re-rendering. I've noticed that on the 2nd time through Firefox 4.0b7 will just sit there and spin as if it is loading. Hitting the stop button on the location bar seems to complete the page render. (Edit: this appears to be fixed in 4.0b8) Also this method seems to prevent the user from hitting refresh to reload the current URL (it reloads the dynamically generated page).

If I use a new DOM tree approach (which has different advantages/disadvantages in flexibility and speed), then this seems to work:

document.replaceChild(newDomDoc, document.documentElement);

Most browsers seem to handle this perfectly fine without flicker. Unfortunately, IE9 beta throws "DOM Exception: HIERARCHY_REQUEST_ERR (3)" on replaceChild and never completes. I haven't tried the latest preview release to see if this is just a new bug that got fixed. (Edit: this appears to be fixed in RC1.)

My question: does anyone have a different approach than either of these? Does anyone have any other caveats where perhaps a particular browser fundamentally breaks down with one of these approaches?

Update: Perhaps this will add context and help the imagination. Consider a situation where an application is offline. There is no server available to redirect or refresh. The necessary state of the application is already loaded (or stored) client-side. The UI is constructed from client-side templates.

I believe that Gmail uses iframes embedded within a root document. It appears the starting document for at least some of these iframes are just a bare HTML5 document which the parent document then manipulates.

Using an iframe would be another variant on the requirement to replace the current document by replacing the entire child iframe or just its document. The same situation exists though of what approach to attach the new document to the iframe.

解决方案

I guess I will answer this with my own findings as I'm wrapping up my research on this.

Since the two browsers which have issues with one of these methods are both beta, I've opened bug reports which hopefully will resolve those before their full release:

I've also found pretty consistently that this...

document.replaceChild(newDomDoc, document.documentElement);

...is 2-10x faster than this...

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

...even when including the time needed to build the DOM nodes vs. build the HTML string. This might be the reason for the flicker, or perhaps just another supporting argument for the DOM approach. Chrome doesn't have any flicker with either method.

Note the subtle change of storing the returned document which circumvents the bug in Firefox 4.0b7.

Also note this added MIME type which the IE docs claim is "required".

Finally, Internet Explorer seems to have a bit of trouble resolving link tags that were built before the new document is swapped in. Assigning the link href back to itself appears to patch it up.

// 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;
        }
    }
}

One could cover all bases and combine them like this...

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

...assuming you have the ability to choose your approach like I do.

这篇关于还有什么其他选项可以通过W3C DOM替换整个HTML文档?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆