blob url可实现每次预览加载全新独立文档上下文,彻底隔离变量、事件监听器和定时器,避免document.write()导致的“identifier 'x' has already been declared”重复声明错误。

为什么 document.write() 在 iframe 预览里会报 “Identifier 'x' has already been declared”
因为每次调用 iframe.contentDocument.write() 会销毁并重建整个文档上下文,但旧的 JS 执行环境(比如已声明的 const 或 let 变量)并未被清除,下次重写时 parser 再次解析同一段脚本,就触发重复声明错误。这不是语法问题,而是执行模型冲突。
- try/catch 捕获不到这个错误——它发生在解析阶段,不是运行时异常
- 清空
iframe.contentDocument后再 write,仍无法解决上下文残留 - 哪怕只改一行 HTML,整个文档都被重载,所有状态丢失
用 Blob URL 替代 srcdoc 或 about:blank + write 的真正原因
srcdoc 和 src="about:blank" 都无法规避文档复用问题;而 Blob URL 是浏览器原生支持的“一次一文档”机制:每次生成新 URL,就对应一个全新、独立、无历史痕迹的文档实例。
-
new Blob([htmlString], {type: 'text/html'})创建内容载体 -
URL.createObjectURL(blob)生成唯一blob:协议地址(自动绑定 null origin) - 赋值给
iframe.src后,浏览器强制加载新文档,彻底隔离变量/事件监听器/定时器 - 记得在
iframe.onload中调用URL.revokeObjectURL(url)防内存泄漏
sandbox="allow-scripts" 为什么不能让 onclick 或内联 script 执行
这是沙箱的设计原则:只允许通过 <script src="..."></script> 加载的外链脚本,所有内联行为(<script>alert(1)</script>、onclick="..."、javascript:void(0)、eval()、Function())全部被静默拦截,控制台无报错。
- 这不是配置遗漏,是浏览器强制执行的“脚本来源白名单”策略
- 若用户输入含内联逻辑,必须提前提取为外部脚本或转成模块化结构
- 加
allow-same-origin对内联执行无效,且不同源时该 token 被浏览器忽略 - localStorage 看似可调用,实则写入后刷新即空,DevTools 的 Application 面板常显示误导信息
如何安全传递状态并避免父页被污染
沙箱 iframe 的 window.parent 默认不可访问,postMessage 是唯一受控通信通道。任何状态同步(如用户点击、表单输入、错误上报)都必须走这条路径,且父页必须校验 event.origin。
- iframe 内不要尝试读写
localStorage或document.cookie,它们绑定到临时 null origin,不持久、不可跨帧共享 - 父页需统一托管状态,iframe 仅负责上报变更:
window.parent.postMessage({type: 'INPUT_CHANGE', value}, '*') - 父页监听时必须检查
event.source === iframe.contentWindow和event.origin === 'null'(Blob URL 下 origin 恒为 null) - 避免在 iframe 中使用
target="_blank"或window.open(),除非显式加allow-popups
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











