javascript - 创建新的 iframe 并同步加载内容
问题描述
目标是动态创建一个 iframe,并同步地将一个 SVG 元素附加到其文档正文中。
我们正试图让它在 Firefox 中工作。
我们的研究表明,Firefox 在将 iframe 附加到 HTML 后会使用新文档重置 iframe。这会触发一个加载事件,只有在此事件之后,您才能成功附加内容。在加载事件之前附加的任何内容都会被丢弃。
不理想的解决方法是等待加载事件,然后将 SVG 元素附加到 iframe。
是否可以避免异步行为?我们希望在创建 iframe 后同步附加 SVG 元素。
代码笔: 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>
解决方案
tl:dr无论做什么,加载的 iframe 的异步特性似乎都无法避免,但是有一种同步方式可以将内容动态添加到 iframe,通过srcdoc
它“覆盖”默认 iframesrc
属性不被使用。
似乎也有使用createHTMLDocument的解决方案,但我还没有成功。
解决方案srcdoc
解释
假设您的动态 iframe 不通过src
属性加载内容
当 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>
.
推荐阅读
- c# - 如何在 C# 中处理有时返回数组、有时返回对象的 JSON 响应
- c# - 如何解决杀死进程的错误?
- java - 编译失败:[...] 无法访问 javax.media.opengl.awt.GLCanvas,找不到 javax.media.opengl.awt.glcanvas 的类文件
- node.js - Slack API - 单击按钮时从同一消息中获取其他组件的值
- ruby-on-rails - 查找别名方法的源位置
- marklogic - 使用 xquery 删除 AppServer 及其所有数据库和林的有效方法
- scala - 如何在运行 sbt run 时更改“主机名”?
- powershell - 无法在 Ironpython 使用 powershell 中获取元素的值
- android - 抽屉通知图标必须是白色的吗?
- x86 - 关于在 x86 上缓存命中存储之前执行缓存未命中加载的指令顺序