代码之家  ›  专栏  ›  技术社区  ›  Kamiel Wanrooij

在使用document.write的HTML中动态插入javascript

  •  17
  • Kamiel Wanrooij  · 技术社区  · 16 年前

    我目前正在加载一个lightbox样式的弹出窗口,它从XHR调用中加载HTML。然后,该内容将显示在“模式”弹出窗口中,使用 element.innerHTML = content 这很有魅力。

    在这个网站的另一个部分,我使用一个Flickr“徽章”( http://www.elliotswan.com/2006/08/06/custom-flickr-badge-api-documentation/ )动态加载Flickr图像。这样做包括一个脚本标记,它加载一个flickr javascript,而这个脚本标记又执行一些操作。 document.write 状态。

    当包含在HTML中时,这两种方法都能很好地工作。仅在加载Flickr徽章代码时 里面 光盒,没有任何内容被渲染。似乎使用 innerHTML 文件编写 语句走得太远了,但我在JavaScript实现(ff2&3,ie6&7)中找不到关于这种行为的任何线索。

    有人能解释一下这是否有效吗?谢谢。

    7 回复  |  直到 7 年前
        1
  •  13
  •   noah    15 年前

    通常,使用innerhtml时不会执行脚本标记。在你的情况下,这很好,因为 document.write 调用将清除页面中已存在的所有内容。但是,这使得您没有HTML document.write应该添加的内容。

    jquery的HTML操作方法将为您执行HTML中的脚本,技巧是捕获对 文件编写 把HTML放在适当的位置。如果它足够简单,那么这样的事情就可以做到:

    var content = '';
    document.write = function(s) {
        content += s;
    };
    // execute the script
    $('#foo').html(markupWithScriptInIt);
    $('#foo .whereverTheDocumentWriteContentGoes').html(content);
    

    不过,事情变得复杂起来。如果脚本在另一个域上,它将被异步加载,因此您必须等到完成后才能获取内容。另外,如果它只是将HTML写到片段的中间,而没有一个您可以轻松选择的包装器元素呢? writeCapture.js (完全公开:我写的)处理所有这些问题。我建议您只使用它,但至少您可以查看代码以了解它是如何处理所有事情的。

    编辑:这里是一个 page 展示你想要的效果。

        2
  •  3
  •   Kamiel Wanrooij    16 年前

    我创建了一个简单的测试页面来说明这个问题:

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    <html>
        <head>
            <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
            <title>Document Write Testcase</title>
        </head>
        <body>
            <div id="container">
            </div>
            <div id="container2">
            </div>
    
            <script>
                // This doesn't work!
                var container = document.getElementById('container');
                container.innerHTML = "<script type='text/javascript'>alert('foo');document.write('bar');<\/script>";
    
                // This does!
                var container2 = document.getElementById('container2');
                var script = document.createElement("script");
                script.type = 'text/javascript';
                script.innerHTML = "alert('bar');document.write('foo');";
                container.appendChild(script);
            </script>
        </body>
    </html>
    

    此页面会提醒“bar”并打印“foo”,而我希望它也会提醒“foo”并打印“bar”。但不幸的是,自从 script 标记是一个更大的HTML页面的一部分,我不能像上面的例子那样单独列出标记并附加它。嗯,我可以,但那需要扫描 innerHTML 内容为 脚本 标记,并用占位符替换字符串中的标记,然后使用DOM插入它们。听起来不是 那个 琐碎的。

        3
  •  3
  •   David Refoua TaW    7 年前

    使用 document.writeln(content); 而不是 document.write(content) .

    然而,最好的方法是使用 innerHTML ,像这样:

    element.innerHTML += content;
    

    这个 element.innerHTML = content; 方法将用新内容替换旧内容,它将覆盖元素的innerhtml!

    反之 += 算子在 element.innerHTML += content; 将在旧内容后添加文本。(像什么?) document.write 是吗?)

        4
  •  1
  •   Mo.    16 年前

    document.write 就跟他们来的时候一样不受欢迎。不过,多亏了javascript的神奇,您可以将自己的函数分配给 write 方法 document 使用的对象 innerHTML 在您选择附加所提供内容的元素上。

        5
  •  0
  •   Jon Cram    16 年前

    我可以先澄清一下,以确保我能解决问题吗?

    document.write 调用将在标记中出现内容时向标记中添加内容。例如,如果您包括 文件编写 在函数中调用,但在其他地方调用该函数, 文件编写 输出将发生在标记中函数是 定义 不在哪里 打电话 .

    因此,要让这一切在所有的Flickr 文件编写 声明必须是 content 在里面 element.innerHTML = content . 确实是这样吗?

    您可以通过添加一个简单的 文件编写 调用设置为 innerHTML 看看这有什么作用:

    <script>
      var content = "<p>1st para</p><script>document.write('<p>2nd para</p>');</script>"
      element.innerHTML = content;
    </script>
    

    如果这是可行的,那么 文件编写 将内容集作为 内层HTML 一个元素可能只起作用。

    我的直觉是它不会起作用,但是测试这个概念应该非常简单。

        6
  •  0
  •   Jon Cram    16 年前

    所以您使用一个dom方法来创建一个 script 元素并将其附加到现有元素,然后这将导致附加的 脚本 要执行的元素?听起来不错。

    您说脚本标记是一个较大的HTML页面的一部分,因此不能单独列出。您不能给脚本标记一个ID并将其作为目标吗?我可能遗漏了一些明显的东西。

        7
  •  0
  •   Kamiel Wanrooij    16 年前

    理论上,是的,我可以用这种方法找出一个脚本标签。问题是,我们可能有几十种情况会发生这种情况,所以我试图找到这种行为的一些原因或文档。

    此外, script 加载后,标记似乎不再是DOM的一部分。在我们的环境中,我的 container DIV仍为空,因此我无法获取 脚本 标签。不过,它应该可以工作,因为在我上面的示例中,脚本没有被执行,但仍然是DOM的一部分。