Javascript 动态创建具有给定 HTML 的 iframe

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10418644/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 01:13:48  来源:igfitidea点击:

Creating an iframe with given HTML dynamically

javascriptiframe

提问by Trevor Burnham

I'm trying to create an iframe from JavaScript and fill it with arbitrary HTML, like so:

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

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

I would expect iframeto then contain a valid window and document. However, this isn't the case:

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

> console.log(iframe.contentWindow);
null

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

Try it for yourself: http://jsfiddle.net/TrevorBurnham/9k9Pe/

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

What am I overlooking?

我在看什么?

采纳答案by GillesC

Setting the srcof a newly created iframein javascript does not trigger the HTML parser until the element is inserted into the document. The HTML is then updated and the HTML parser will be invoked and process the attribute as expected.

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

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

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

Also this answer your question it's important to note that this approach has compatibility issues with some browsers, please see the answer of @mschr for a cross-browser solution.

此外,此回答您的问题很重要,请注意此方法与某些浏览器存在兼容性问题,请参阅@mschr 的答案以获取跨浏览器解决方案。

回答by mschr

Allthough your src = encodeURIshould work, I would have gone a different way:

虽然你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();

As this has no x-domain restraints and is completely done via the iframehandle, you may access and manipulate the contents of the frame later on. All you need to make sure of is, that the contents have been rendered, which will (depending on browser type) start during/after the .write command is issued - butnot nescessarily done when close()is called.

由于这没有 x 域限制并且完全通过iframe句柄完成,您可以稍后访问和操作框架的内容。您需要确保的是,内容已经呈现,这将(取决于浏览器类型)在 .write 命令发出期间/之后开始 -close()调用时不一定完成。

A 100% compatible way of doing a callback could be this approach:

100% 兼容的回调方法可能是这种方法:

<html><body onload="parent.myCallbackFunc(this.window)"></body></html>

Iframes has the onload event, however. Here is an approach to access the inner html as DOM (js):

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

iframe.onload = function() {
   var div=iframe.contentWindow.document.getElementById('mydiv');
};

回答by kylewelsby

Thanks for your great question, this has caught me out a few times. When using dataURI HTML source, I find that I have to define a complete HTML document.

感谢您提出的好问题,这让我不知所措。在使用 dataURI HTML 源时,我发现我必须定义一个完整的 HTML 文档。

See below a modified example.

请参阅下面的修改示例。

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

take note of the html content wrapped with <html>tags and the iframe.srcstring.

注意用<html>标签和iframe.src字符串包装的 html 内容。

The iframe element needs to be added to the DOM tree to be parsed.

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

document.body.appendChild(iframe);

You will not be able to inspect the iframe.contentDocumentunless you disable-web-securityon your browser. You'll get a message

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

DOMException: Failed to read the 'contentDocument' property from 'HTMLIFrameElement': Blocked a frame with origin "http://localhost:7357" from accessing a cross-origin frame.

DOMException: 无法从“HTMLIFrameElement”读取“contentDocument”属性:阻止了来自“ http://localhost:7357”的框架访问跨源框架。

回答by zedd45

There is an alternative for creating an iframe whose contents are a string of HTML: the srcdoc attribute. This is not supported in older browsers (chief among them: Internet Explorer, and possibly Safari?), but there is a polyfillfor this behavior, which you could put in conditional comments for IE, or use something like has.js to conditionally lazy load it.

有一种替代方法可以创建内容为 HTML 字符串的 iframe:srcdoc 属性。这在较旧的浏览器中不受支持(其中主要是:Internet Explorer,可能还有 Safari?),但是这种行为有一个polyfill,你可以在 IE 中添加条件注释,或者使用诸如 has.js 之类的东西来有条件地懒惰加载它。

回答by Dominique Fortin

Do this

做这个

...
var el = document.getElementById('targetFrame');

var frame_win = getIframeWindow(el);

console.log(frame_win);
...

getIframeWindowis defined here

getIframeWindow在这里定义

function getIframeWindow(iframe_object) {
  var doc;

  if (iframe_object.contentWindow) {
    return iframe_object.contentWindow;
  }

  if (iframe_object.window) {
    return iframe_object.window;
  } 

  if (!doc && iframe_object.contentDocument) {
    doc = iframe_object.contentDocument;
  } 

  if (!doc && iframe_object.document) {
    doc = iframe_object.document;
  }

  if (doc && doc.defaultView) {
   return doc.defaultView;
  }

  if (doc && doc.parentWindow) {
    return doc.parentWindow;
  }

  return undefined;
}

回答by frobinsonj

I know this is an old question but I thought I would provide an example using the srcdocattribute as this is now widely supportedand this is question is viewed often.

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

Using the srcdocattribute, you can provide inline HTML to embed. It overrides the srcattribute if supported. The browser will fall back to the srcattribute if unsupported.

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

I would also recommend using the sandboxattribute to apply extra restrictions to the content in the frame. This is especially important if the HTML is not your own.

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

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

If you need to support older browsers, you can check for srcdocsupport and fallback to one of the other methods from other answers.

如果您需要支持较旧的浏览器,您可以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);