关于javascript:动态创建具有给定HTML的iframe

Creating an iframe with given HTML dynamically

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

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

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

> console.log(iframe.contentWindow);
null

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

我在俯视什么?


尽管您的src = encodeURI应该可以工作,但我会采取另一种方式:

1
2
3
4
5
6
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();

由于这没有x域限制,并且完全通过iframe句柄完成,因此以后您可以访问和操纵帧的内容。您需要确定的是,已呈现了内容,该内容将(根据浏览器类型)在发出.write命令期间/之后开始-但在调用close()时不一定要做。

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

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

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

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


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

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

1
2
3
4
5
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);

同样,这个问题也回答了您,很重要的一点是,这种方法与某些浏览器存在兼容性问题,请参阅@mschr的跨浏览器解决方案。


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

参见下面的修改示例。

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

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

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

1
document.body.appendChild(iframe);

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

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


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


做这个

1
2
3
4
5
6
7
...
var el = document.getElementById('targetFrame');

var frame_win = getIframeWindow(el);

console.log(frame_win);
...

getIframeWindow在这里定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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;
}