创建新的iframe并同步加载内容

时间:2019-05-18 03:02:33

标签: javascript jquery html firefox iframe

目标是动态创建iframe,并将SVG元素同步同步添加到其文档正文中。

我们正在尝试使其在Firefox中正常工作。

我们的研究表明,在将iframe附加到HTML之后,Firefox会使用新文档重置iframe。这将触发加载事件,并且只有在此事件之后,您才能成功附加内容。加载事件之前附加的所有内容都将被丢弃。

不理想的解决方法是等待加载事件,然后将SVG元素附加到iframe。

是否可以避免异步行为?我们要在创建iframe后同步添加SVG元素。

Codepen:https://codepen.io/anon/pen/yWXjgM

var newElem = $(document.createElement("div"));
newElem.html("hi there");
var iframe = $(document.createElement("iframe"));
iframe.contents().find("body").append(newElem);
$("#box").append(iframe);
$("#box").append(newElem);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="box"></div>

1 个答案:

答案 0 :(得分:1)

tl:dr 不管执行什么操作,都无法避免出现正在加载的iframe的异步特性,但可以通过同步方式添加内容通过srcdoc动态地移至iframe,从而“覆盖”默认的iframe src属性,使其不再使用。

它似乎还会出现 使用createHTMLDocument的解决方案,但是我还没有成功。

使用srcdoc

的解决方案

说明

假设您的动态iframe不会通过src属性加载内容

根据HTML iframe specifications

  

将iframe元素插入具有浏览上下文的文档中时,用户代理必须创建一个嵌套的浏览上下文,然后“第一次”处理iframe属性。

需要注意的事情是“第一次处理iframe属性”。 没有提及,该过程是同步的还是异步的,取决于每个浏览器的实现。

正如已经提到的,Chrome和Firefox将这个过程理解为异步的,这确实有意义,因为iframe的目标是从其src属性中加载内容并调用onload回调。

如果没有src属性可用,则将其设置为"about:blank"

值得一提的是,在浏览器检查是否存在src属性之前,它将首先检查srcdoc是否可用,根据MDN iframe doc

  

srcdoc

     

要嵌入的内联HTML,覆盖src属性。如果浏览器不支持srcdoc属性,它将退回到src属性中的URL。

工作示例

const container = document.getElementById("container");
const iframe = document.createElement("iframe");

iframe.addEventListener("load", function(){
  console.log("loaded...");
});

iframe.srcdoc = `
  <svg height="100" width="100">
      <circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" />
      Sorry, your browser does not support inline SVG.  
  </svg>
`;

iframe.srcdoc += `
  <svg height="100" width="100">
      <circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="blue" />
      Sorry, your browser does not support inline SVG.  
  </svg>
`

container.append(iframe);
<div id="container"></div>

Web扩展解决方案

如果您正在开发Web扩展程序,则可以访问mozbrowser api,因此可以访问stop

  

HTMLIFrameElement接口的stop()方法用于停止加载<iframe>的内容。