同源前提下iframe子页面可通过parent.document直接读写父页面DOM;需确保父页面DOM就绪、ID唯一,避免多层parent或过早操作;跨域时必须用postMessage通信并校验origin。

iframe子页面用parent.document访问父页面DOM
同源前提下,子页面能直接读写父页面的DOM,核心是拿到parent.document对象。它不是window.parent.document的简写——虽然两者等价,但parent更短、更常用,且在所有现代浏览器中行为一致。
常见错误是误用window.parent.parent.document(多了一层parent),或在iframe未加载完成时就执行操作,导致getElementById返回null。
- 确保父页面元素已存在且ID唯一,比如
<div id="header"></div> - 子页面脚本应放在
底部,或监听DOMContentLoaded,避免DOM未就绪 - 不要依赖
document.write或同步脚本注入,容易触发竞态
jQuery里用$("#id", parent.document)选中父元素
如果父页面用了jQuery,子页面也引入了jQuery,可以直接用上下文选择器语法:传入parent.document作为第二个参数。这比手动调用parent.document.getElementById更符合jQuery习惯,也自动处理了节点查找逻辑。
注意:parent.$不一定可用——除非父页面把$挂到了window上且未被覆盖;而parent.document始终可靠。
立即学习“前端免费学习笔记(深入)”;
将 Markdown 文章转换为微信公众号兼容的纯 HTML 格式。当用户要求"转成微信格式"、"生成公众号文章 HTML"、"排版到微信草稿箱"、"微信粘贴格式"时触发。输出带内联样式的纯 HTML,微信编辑器可直接渲染,无需额外适配。支持标题、段落、列表、粗体、行内代码、表格、引用块、代码块、配图的完整转换。
- 正确写法:
$("#menu", parent.document).show() - 错误写法:
parent.$("#menu").show()(可能报parent.$ is not a function) - 若父页面用的是
jQuery.noConflict(),则parent.jQuery可能有效,但不如直接用原生parent.document稳妥
修改父页面样式或属性前,先检查contentWindow是否就绪
iframe加载是异步的,子页面JS执行时,父页面DOM可能还没解析完,也可能父页面脚本尚未初始化某些变量。尤其当父页面有动态渲染(如React/Vue挂载)、或依赖外部JS库时,直接操作容易报错。
简单判断方式是用parent.document.readyState === "complete",但更健壮的做法是封装一个重试或事件监听:
- 子页面可监听
parent.document的DOMContentLoaded(需父页面主动派发,不通用) - 推荐轮询:
function tryAccess() { if (parent.document.getElementById("target")) { /* 操作 */ } else setTimeout(tryAccess, 50); } - 避免用
window.onload——它等全部资源(含图片),太慢;用DOMContentLoaded即可
跨域时parent.document完全不可用,必须换方案
一旦iframe的src和父页面协议、域名、端口任一不同,浏览器会抛出SecurityError,所有对parent.document的访问都会失败,连typeof parent.document都可能报错。
此时唯一标准解法是window.postMessage,由子页面发消息,父页面监听并响应。不能绕过,也不能用document.domain降域(仅适用于同主域不同子域,且现代浏览器已逐步弃用)。
- 子页面发送:
parent.postMessage({ action: "updateHeader", text: "New Title" }, "https://parent-domain.com") - 父页面监听:
window.addEventListener("message", handler),并在handler里校验event.origin - 漏掉
event.origin校验等于开后门,极易被恶意iframe利用
父页面与iframe之间的DOM访问看似简单,真正难的是边界情况:加载时机、跨域限制、框架干扰(比如Vue的响应式代理可能拦截innerHTML赋值)、以及调试时看不到错误堆栈(因跨域脚本无法读取)。动手前先确认同源性,再决定走直连还是postMessage。


















