替换整个HTML文档(原地)

10

我试图避免使用数据URI,因为我不希望生成的文档存储在浏览器历史记录中。是否可能原地替换整个HTML文档?

我尝试了jQuery("html").html("<html>....</html>"),但style信息无法保存。


我对你的说法“样式信息不会保留”感到困惑,样式将与文档链接或包含在文档中,因此如果您替换整个文档,您会期望丢失样式?您真的需要替换/整个/文档吗?从游客的角度来看,您想要实现什么? - Andrew M
抱歉,我的意思是 新的 样式信息 .html("...<style>...</style>...") 无法保存。 - james
我没有意识到你在谈论新的样式信息。那个评论让我想了一下;我稍微更新了我的答案。 - T.J. Crowder
也许这个答案会有所帮助。 - Salma Gomaa
也许这个答案有帮助 https://dev59.com/6HM_5IYBdhLWcg3ww2Kb#1236378 - Salma Gomaa
2个回答

16

你可能想要这样做:

jQuery("body").html("new content");

在替换 body 元素内容时,"new content" 最好只包含正常出现在 body 元素中的标记而不包括其他内容。这将替换 body 元素的内容,同时保留您在 head 中拥有的任何内容(如样式表信息)。如果您还想更新标题,可以使用 document.title = "new title";

编辑 我开始思考替换 html 元素内的 所有 内容是否可行,以及会发生什么。所以我做了这个:

<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
<title>Test Page</title>
<style type='text/css'>
body {
    font-family: sans-serif;
    font-weight: bold;
    color:       blue;
}
</style>
<script type='text/javascript' src='http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js'></script>
<script type='text/javascript'>
(function() {
    $(document).ready(pageInit);
    function pageInit() {
        $('#btnChange').live('click', changePage);
        $('#btnHiThere').live('click', sayHi);
    }

    function changePage() {
        $('html').html(
            "<head><\/head>" +
            "<body>" +
            "<input type='button' id='btnHiThere' value='Click for Alert'>" +
            "<p>Note how this text now looks.<\/p>" +
            "<\/body>"
        );
    }

    function sayHi() {
        alert("Hi there");
    }
})();
</script>
</head>
<body>
<input type='button' id='btnHiThere' value='Click for Alert'>
<input type='button' id='btnChange' value='Change Page'>
<p>Note now this text current appears in a sans-serif, bold, blue font.</p>
</body>
</html>

结果非常有趣— 我最终得到的DOM结构完全没有headbody,只有html及其内部的headbody后代。这可能是新内容中样式出现问题的原因。如果我直接设置innerHTML,基本上会得到相同的结果(这可能是为什么它在jQuery中不起作用的原因;jQuery在可以使用innerHTML时使用它,尽管在无法使用时非常复杂)。但是,如果通过document.createElementdocument.appendChild显式创建headbody元素,它可以正常工作。

所有这些几乎肯定意味着这比它值得的更费力。

但是:请注意,更改headbody元素的内容似乎完全没问题:

<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
<title>Test Page</title>
<style type='text/css'>
body {
    font-family: sans-serif;
    font-weight: bold;
    color:       blue;
}
</style>
<script type='text/javascript' src='http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js'></script>
<script type='text/javascript'>
(function() {
    $(document).ready(pageInit);
    function pageInit() {
        $('#btnChange').live('click', changePage);
        $('#btnHiThere').live('click', sayHi);
    }

    function changePage() {
        $('head').html(
            "<style type='text/css'>\n" +
            "body { color: green; }\n" +
            "<\/style>\n"
        );
        $('body').html(
            "<input type='button' id='btnHiThere' value='Click for Alert'>" +
            "<p>Note how this text now looks.<\/p>"
        );
    }

    function sayHi() {
        alert("Hi there");
    }
})();
</script>
</head>
<body>
<input type='button' id='btnHiThere' value='Click for Alert'>
<input type='button' id='btnChange' value='Change Page'>
<p>Note now this text current appears in a sans-serif, bold, blue font.</p>
</body>
</html>

如果你将要加载的“页面”分成头部和主体两个部分,那么你可以方便地直接更新其中一部分。


那么无法加载新的<head>标签吗? - james
@james:这可能是可行的,但如果你这样做,你需要确保它仍然拥有你想要的所有内容(例如样式表引用)。你可能不必担心维护脚本标签;一旦脚本被加载和评估,它就不再绑定到创建它的元素上,删除元素对脚本没有影响。 - T.J. Crowder
我要注意一下(虽然有点晚了),在头部存在大量JS(例如通过Optimizely或Ensighten)甚至可能使仅替换正文也变得不可行。 - Melissa Avery-Weir

2

没有jQuery:

var newString = [
      "<!doctype html>"
    , "<html>"
    , "<head>"
    , "</head>"
    , "<body>"
    , "<h1>new content</h1>"
    , "</body>"
    , "</html>"
].join("");

document.getElementById('myIframeId').contentDocument.documentElement.outerHTML = newString;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接