重置/重新加载 IFrame JavaScript 上下文



我正在创建一个由文本框和<iframe>元素组成的交互式代码编辑器。每当用户在文本框中键入代码时,都会写入 IFrame 的内容,并使用代码文本框的内容填充 IFrame 内的<script>标记,从而使用户键入的代码在 IFrame 中运行。每次用户键入时,都应重置/重新加载 IFrame,并使用 IFrame 脚本标记中文本框的新内容再次写入文档,实质上是在他们键入时自动运行他们键入的任何代码。

但是,在执行此操作时,我注意到命名空间冲突是由于用户在其代码中声明的变量将在 IFrame 刷新之间保留。我通过将插入的代码包装到 IIFE 中来解决此问题,但随后注意到当用户运行一个循环然后重新加载 IFrame 两次时,将运行两个循环。

显然,IFrame 的 JavaScript 上下文没有被重置。我已经尝试了这里给出的答案,包括使用.contentWindow.location.reload()重新加载 IFrame 以及用.src = "about:blank"更改 IFrame 源,但这些只是重置文档的内容,而不是 IFrame JavaScript 上下文,如果 IFrame 位于同一域上,则根据这些答案,IFrame 上下文将保持不变。

这是我正在使用的实际代码(克隆存储库 -> 运行npm install->运行npm run dev-> 打开examples/Sandbox/index.html(。

下面是该问题的最小可重现示例(依赖于 ID 为frame的 IFrame 元素的存在(:

const frame = document.getElementById("frame");
let i = 1;
function updateFrame() {
frame.contentWindow.location.reload();
frame.contentDocument.open();
frame.contentDocument.write(`
<html>
<body>
<script>
(function() {
let a = 0;
function print() {
console.log(${i++} + ": " + a++);
requestAnimationFrame(print);
}
print();
})();
</script>
</body>
</html>
`);
frame.contentDocument.close();
}
updateFrame();
updateFrame();

请参阅JSFiddle。

请注意,updateFrame()被调用了两次,这应该重新加载 IFrame 的内容,只留下第二个循环运行,但是两个print()循环同时打印到控制台,这表明上下文在整个重新加载过程中保持不变。

预期的行为是 IFrame 内容JavaScript 上下文应在重新加载之间完全重置。在该示例中,只应重复打印2: ...到控制台,而不是同时打印1: ...2: ...。如何刷新 IFrame,使其 JavaScript 上下文不会在整个重新加载过程中持久化,并且本质上与手动重新加载页面相同?

创建 IFrame 后,您将无法编辑其源代码,以防止人们使用 IFrames 将代码注入网站以窃取信息等,或创建包含恶意代码的虚假网站,其中包含恶意代码以其他安全域。

您必须通过 AJAX 将更新从编辑器渲染到后端(如 PHP 服务器或节点(.js或者完全删除 IFrame 元素并创建一个全新的元素

var if = document.createElement("IFRAME");
if.src = /* your code */
var container = document.getElementById("container");

然后,每次需要更新时,使用类似的系统删除该项目。

container.innerHTML = "";

最新更新