为啥将 <script> 附加到动态创建的 <iframe> 似乎会在父页面中运行脚本?

Posted

技术标签:

【中文标题】为啥将 <script> 附加到动态创建的 <iframe> 似乎会在父页面中运行脚本?【英文标题】:Why does appending a <script> to a dynamically created <iframe> seem to run the script in the parent page?为什么将 <script> 附加到动态创建的 <iframe> 似乎会在父页面中运行脚本? 【发布时间】:2010-12-08 03:33:16 【问题描述】:

我正在尝试使用 javascript 创建一个

不幸的是,我似乎做错了——我的 JavaScript 似乎执行成功,但

这是我正在使用的代码(http://onespot.wsj.com/static/iframe_test.html 的现场演示):

iframe_test.html

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title>&lt;iframe&gt; test</title>
  </head>
  <body>
    <div id="bucket"></div>
    <script type="text/javascript" src="http://jqueryjs.googlecode.com/files/jquery-1.3.2.min.js"></script>
    <script type="text/javascript">
      $(document).ready(function() 
        $('#bucket').append('<iframe id="test"></iframe>');
        setTimeout(function() 
          var iframe_body = $('#test').contents().find('body');
          iframe_body.append('<scr' + 'ipt type="text/javascript" src="http://onespot.wsj.com/static/iframe_test.js"></scr' + 'ipt>');
        , 100);
      );
    </script>
  </body>
</html>

iframe_test.js

$(function() 
  var test = '<p>Shouldn\'t this be inside the &lt;iframe&gt;?</p>';
  $('body').append(test);
);

一件看起来不寻常的事情是 iframe_test.js 中的代码甚至可以工作;我没有在

任何想法、建议等将不胜感激!

【问题讨论】:

也许这与 这是为了防止跨站点脚本的设计。如果您可以按照您尝试的方式将脚本注入另一个站点,您可以将脚本从任何 iframe 容器注入到任何网站,而不会出现问题。 好吧,我认为“相同域”规则会阻止向 iframe 中的文档添加任何内容。但是,如果文档来自同一个域,则规则不适用。 @Pointy - 非常感谢您的意见。你的想法听起来可行——我试了一下,但没能成功(尽管这并不意味着它不是一个有效的解决方案)。我最终在下面的答案中使用了代码,这对我的目的来说是一个更优雅的解决方案。 @Nissan Fan - 感谢您的反馈。然而,Pointy 是正确的——因为这个 【参考方案1】:

遇到了同样的问题,花了我几个小时才找到解决方案。 您只需要使用 iframe 的文档创建脚本的对象。

var myIframe = document.getElementById("myIframeId");
var script = myIframe.contentWindow.document.createElement("script");
script.type = "text/javascript";
script.src = src;
myIframe.contentWindow.document.body.appendChild(script);

像魅力一样工作!

【讨论】:

太棒了......从几个小时开始就在做同样的事情......现在修好了 @user2284570 有办法跨域吗? @StanJames:不知道,但这通常会导致在没有ᴄᴏʀꜱ的情况下跨 AJAX。 @StanJames 跨域 iframe 是完全不同的球类游戏。即使有解决方案,浏览器也会很快找到它们的路径。这是一项安全功能,可防止坏人破解您的银行密码等。 顺便说一句,为了浏览器的兼容性,我建议将它用于内容窗口:var doc = iframe.contentDocument ? iframe.contentDocument : (iframe.contentWindow ? iframe.contentWindow.document : iframe.document);【参考方案2】:

我没有找到原始问题的答案,但我确实找到了另一种效果更好的方法(至少对于我的目的而言)。

这不会在父页面上使用 jQuery(这实际上是一件好事,因为我不想在那里加载它),但它确实在

代码:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title>frame</title>
  </head>
  <body>

    <div id="test"></div>

    <script type="text/javascript">
      // create a new <iframe> element
      var iframe = document.createElement('iframe');

      // append the new element to the <div id="bucket"></div>
      var bucket = document.getElementById('test');
      bucket.appendChild(iframe);

      // create a string to use as a new document object
      var val = '<scr' + 'ipt type="text/javascript" src="http://jqueryjs.googlecode.com/files/jquery-1.3.2.min.js"></scr' + 'ipt>';
      val += '<scr' + 'ipt type="text/javascript"> $(function()  $("body").append("<h1>It works!</h1>"); ); </scr' + 'ipt>';

      // get a handle on the <iframe>d document (in a cross-browser way)
      var doc = iframe.contentWindow || iframe.contentDocument;
      if (doc.document) 
        doc = doc.document;
      

      // open, write content to, and close the document
      doc.open();
      doc.write(val);
      doc.close();
    </script>

  </body>
</html>

我希望这对以后的人有所帮助!

【讨论】:

这正是我正在寻找的。有什么办法可以追加到 iframe 中,这样正文内容就不会被删除? 为什么直接写'&lt;scr' + 'ipt而不是'&lt;script @user2284570:浏览器会按字面意思解释内联 &lt;script&gt; 标签中的任何 HTML 字符串,因此像 var endScript = '&lt;/script&gt;'; 这样的东西会被解释为当前脚本的过早结束标签,从而导致语法错误。 在 iframe 中粘贴包含 script 标签的整个 html 内容时非常有用 但这有一个缺点,因为doc.write 仅在整个页面加载时才开始写入。【参考方案3】:

原始问题的答案很简单 - 脚本的执行是由 jquery 完成的,并且由于 jquery 加载在顶部框架中,因此无论您将脚本附加到何处,这也是脚本运行的地方。毫无疑问,jquery 的更智能实现可以使用正确的窗口对象,但现在情况就是这样。

至于解决方法,您已经有了两个很好的答案(即使一个是您自己的)。我可能要补充的是,您可以使用其中一种解决方法将 jquery.js 包含在 iframe 中,然后获取该 jquery 对象而不是顶部对象来插入您的附加标记......但这也可能是矫枉过正。

【讨论】:

以上是关于为啥将 <script> 附加到动态创建的 <iframe> 似乎会在父页面中运行脚本?的主要内容,如果未能解决你的问题,请参考以下文章

DOMParser 将 <script> 标记附加到 <head>/<body> 但不执行

无法附加 <script> 元素

React:如何将不同类型的子组件动态附加到父组件中?

为啥附加到列表的值会动态变化?

根据时间在脚本标签和样式表中附加动态版本(变量)

将元素附加或添加到页面正文