动态创建具有给定HTML的iframe

Tre*_*ham 135 javascript iframe

我正在尝试从JavaScript创建一个iframe并用任意HTML填充它,如下所示:

var html = '<body>Foo</body>';
var iframe = document.createElement('iframe');
iframe.src = 'data:text/html;charset=utf-8,' + encodeURI(html);
Run Code Online (Sandbox Code Playgroud)

我希望iframe然后包含一个有效的窗口和文档.但是,情况并非如此:

> console.log(iframe.contentWindow);
空值

亲自试试:http://jsfiddle.net/TrevorBurnham/9k9Pe/

我在俯瞰什么?

msc*_*chr 215

虽然你src = encodeURI应该工作,但我会采取不同的方式:

var iframe = document.createElement('iframe');
var html = '<body>Foo</body>';
document.body.appendChild(iframe);
iframe.contentWindow.document.open();
iframe.contentWindow.document.write(html);
iframe.contentWindow.document.close();
Run Code Online (Sandbox Code Playgroud)

由于它没有x域限制并且完全通过iframe句柄完成,因此您可以稍后访问和操作帧的内容.所有你需要确保的是,内容已经被渲染,这将(在浏览器类型的基础上)在发出.write命令期间/之后开始 - 但是close()调用时不是必须完成的.

这种方法可以采用100%兼容的方式进行回调:

<html><body onload="parent.myCallbackFunc(this.window)"></body></html>
Run Code Online (Sandbox Code Playgroud)

但是,iframe具有onload事件.这是一种访问内部html为DOM(js)的方法:

iframe.onload = function() {
   var div=iframe.contentWindow.document.getElementById('mydiv');
};
Run Code Online (Sandbox Code Playgroud)

  • 基本上,是的,我相信它应该,在那里发表评论.该技术基本上打开了一个inputtextstream,您可以通过document.write写入该文本流.反过来,正常的加载网页通过websocket流来回溯. (2认同)
  • 这适用于Internet Explorer!这很方便,因为数据URI不能在任何版本的IE中用作iframe源.http://caniuse.com/#feat=datauri (2认同)
  • 有趣的是,需要 `document.body.appendChild(iframe)` 才能工作。 (2认同)

Gil*_*esC 114

在将元素插入到文档中之前,设置javascript中src新创建的iframe不会触发HTML解析器.然后更新HTML并调用HTML解析器并按预期处理该属性.

http://jsfiddle.net/9k9Pe/2/

var iframe = document.createElement('iframe');
var html = '<body>Foo</body>';
iframe.src = 'data:text/html;charset=utf-8,' + encodeURI(html);
document.body.appendChild(iframe);
console.log('iframe.contentWindow =', iframe.contentWindow);
Run Code Online (Sandbox Code Playgroud)

这也回答了你的问题,重要的是要注意这种方法与某些浏览器存在兼容性问题,请参阅@mschr的答案以获得跨浏览器解决方案.

  • 他的问题是"我在俯视什么?" 这就是iframe没有附加到文档的事实.我从来没有声称它是跨浏览器,而且仅仅在我回答有人抱怨的一年之后.不,它不是跨浏览器.但是说实话,如果你想要代码质量,那么可能比使用iframe更清晰的解决方案:) (5认同)
  • 在IE9中快速检查它并且它不起作用 (3认同)
  • 甚至不在IE10中工作.@mschr的答案肯定适用于IE7 +,甚至可能是旧版本. (3认同)
  • 请注意,[`encodeURI(...)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURI) 不会对所有字符进行编码,因此如果您的 HTML有像“#”这样的特殊字符,这会中断。[`encodeURIComponent(...)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent) 对这些字符进行编码。请参阅[此答案](/sf/ask/646722331/) (2认同)

hal*_*ube 12

谢谢你的好问题,这让我感到很沮丧.使用dataURI HTML源代码时,我发现我必须定义一个完整的HTML文档.

请参阅下面的修改示例.

var html = '<html><head></head><body>Foo</body></html>';
var iframe = document.createElement('iframe');
iframe.src = 'data:text/html;charset=utf-8,' + encodeURI(html);
Run Code Online (Sandbox Code Playgroud)

记下用<html>标签和iframe.src字符串包装的html内容.

需要将iframe元素添加到要解析的DOM树中.

document.body.appendChild(iframe);
Run Code Online (Sandbox Code Playgroud)

iframe.contentDocument除非您disable-web-security在浏览器上,否则您将无法检查.你会收到一条消息

DOMException:无法从'HTMLIFrameElement'读取'contentDocument'属性:阻止具有原始" http:// localhost:7357 "的帧访问跨源帧.


zed*_*d45 11

还有一种方法可以创建一个iframe,其内容是HTML字符串:srcdoc属性.旧版浏览器(主要是Internet Explorer,可能还有Safari?)不支持这种情况,但是这种行为有一个polyfill,你可以把它放在IE的条件注释中,或者使用像has.js这样有条件的懒惰加载它.

  • 现在对此的支持非常主流(保存IE)。而且绝对比直接访问contentDocument更可取-特别是因为如果与sandbox属性结合使用,则无法访问contentDocument。 (2认同)

fro*_*onj 10

我知道这是一个老问题,但我想我会提供一个使用该srcdoc属性的示例,因为它现在得到广泛支持,并且经常查看这个问题。

使用该srcdoc属性,您可以提供要嵌入的内联 HTML。src如果支持,它会覆盖该属性。src如果不支持,浏览器将回退到该属性。

我还建议使用该sandbox属性对框架中的内容应用额外的限制。如果 HTML 不是您自己的,这一点尤其重要。

const iframe = document.createElement('iframe');
const html = '<body>Foo</body>';
iframe.srcdoc = html;
iframe.sandbox = '';
document.body.appendChild(iframe);
Run Code Online (Sandbox Code Playgroud)

如果您需要支持较旧的浏览器,您可以srcdoc从其他答案中检查是否支持并回退到其他方法之一。

function setIframeHTML(iframe, html) {
  if (typeof iframe.srcdoc !== 'undefined') {
    iframe.srcdoc = html;
  } else {
    iframe.sandbox = 'allow-same-origin';
    iframe.contentWindow.document.open();
    iframe.contentWindow.document.write(html);
    iframe.contentWindow.document.close();
  }
}

var iframe = document.createElement('iframe');
iframe.sandbox = '';
var html = '<body>Foo</body>';

document.body.appendChild(iframe);
setIframeHTML(iframe, html);
Run Code Online (Sandbox Code Playgroud)


小智 5

URL 方法仅适用于小的 HTML 片段。更可靠的方法是从 blob 生成对象 URL,并将其用作动态 iframe 的源。

const html = '<html>...</html>';
const iframe = document.createElement('iframe');
const blob = new Blob([html], {type: 'text/html'});
iframe.src = window.URL.createObjectURL(blob);
document.body.appendChild(iframe);
Run Code Online (Sandbox Code Playgroud)