iframe是什么
<iframe>
是 HTML 提供的“页中页”标签,它能在当前文档内嵌入一个独立的浏览上下文,拥有自己完整的 window、DOM、CSS 和 JavaScript 运行环境,天然与父页面隔离;借助 postMessage、sandbox、allow 等 API 与安全属性,开发者既可在跨域场景下安全地通信与限制权限,又能通过懒加载、预连接等手段优化性能,因此常被用于第三方内容嵌入、微前端子应用、支付收银台、在线文档预览等需要“隔离 + 互动”的业务场景。
应用场景
- iframe 把“独立页”嵌入主文档,天然隔离又支持 postMessage 通信,因此常用来加载第三方支付页、微前端子应用、跨域上传组件、在线文档预览、广告或地图等需要安全沙箱、样式隔离、懒加载的模块,既避免脚本冲突,又能随取随用、按需销毁。
通信方式
同源
- 父页面和 iframe 的源(协议 + 域名 + 端口)完全相同,因此浏览器允许它们直接互相访问对方的 document、window 和 DOM 节点,无需任何消息转发或 postMessage。
例如下面代码块
const childDoc = window.frames[0].document;
childDoc.body.style.background = '#000';
window.parent.document.getElementById('header').innerText = 'Hi from iframe';
跨域
- 双方先 window.addEventListener(‘message’, handler) 注册监听器;
- 发消息用 otherWindow.postMessage(data, origin),data 最好是结构化克隆对象,origin 必须精确匹配,避免 “*”;
例如下列代码块:
if (window.parent !== window) {window.parent.postMessage({type: 'mock_data',data: mockData,source: 'iframe'}, '*'); console.log('数据已发送到父页面:', mockData);alert('数据已成功发送到父页面!');} else {alert('当前页面不是iframe,无法发送数据到父页面');}
视频演示
- 下面这两个网页实现了一个iframe父子页面通信的演示系统。子页面(iframe.html)负责生成包含用户名、用户ID、消息内容和时间戳的模拟数据,并通过点击"发送数据到父页面"按钮,使用postMessage API将数据发送给父页面。父页面(parent.html)则通过监听message事件来接收来自子页面的数据,并以美观的卡片形式在页面上方展示接收到的用户信息、消息内容和时间戳,实现了跨域iframe之间的安全数据通信功能。

代码部分
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>iframe父页面</title></head><style>#parent {background-color: aqua;}iframe {width: 80vw;height: 80vh;}</style><body><div id="parent"><h1>这是父页面</h1><div id="received-data">等待接收数据...</div><iframe src="iframe.html" frameborder="0"></iframe></div></body><script>window.addEventListener("message", function (event) {const data = event.data;if (data.type === "mock_data" && data.source === "iframe") {console.log("父页面收到数据:", data.data);displayReceivedData(data.data);}});function displayReceivedData(mockData) {const container = document.getElementById("received-data");let html = "<h3>从子页面接收到的Mock数据:</h3>";mockData.forEach((item, index) => {html += `<div class="received-message"><strong>消息 ${index + 1}:</strong><br><strong>用户:</strong> ${item.userName} (ID: ${item.userId})<br><strong>消息内容:</strong> ${item.message}<br><strong>时间:</strong> ${item.timestamp}</div>`;});html += `<div class="data-info">共收到 ${mockData.length} 条消息</div>`;container.innerHTML = html;container.scrollTop = container.scrollHeight;}</script>
</html>
iframe子页面代码
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>iframe子页面</title></head><style>#iframe {background-color: rgb(255, 204, 0);width: 80vw;height: 80vh;}</style><body><div id="iframe"><h1>这是子页面</h1><div id="messages-container"></div><button id="send-btn">发送</button></div></body><script>function generateMockData() {const users = [{ id: 1001, name: "张三" },{ id: 1002, name: "李四" },{ id: 1003, name: "王五" },{ id: 1004, name: "赵六" },{ id: 1005, name: "钱七" },];const messages = ["你好,今天天气不错!","这个功能看起来很棒!","我同意你的观点","有什么新的更新吗?","感谢分享这些信息","期待下次的会议","这个设计很漂亮","代码运行得很顺利","需要帮忙吗?","完成得很棒!",];const mockData = [];for (let i = 0; i < 10; i++) {const randomUser = users[Math.floor(Math.random() * users.length)];const randomMessage =messages[Math.floor(Math.random() * messages.length)];const randomDaysAgo = Math.floor(Math.random() * 7);const randomHoursAgo = Math.floor(Math.random() * 24);const randomMinutesAgo = Math.floor(Math.random() * 60);const timestamp = new Date();timestamp.setDate(timestamp.getDate() - randomDaysAgo);timestamp.setHours(timestamp.getHours() - randomHoursAgo);timestamp.setMinutes(timestamp.getMinutes() - randomMinutesAgo);mockData.push({userId: randomUser.id,userName: randomUser.name,message: randomMessage,timestamp: timestamp.toLocaleString("zh-CN"),});}return mockData;}function displayMockData() {const container = document.getElementById('messages-container');const mockData = generateMockData();mockData.forEach(data => {const messageDiv = document.createElement('div');messageDiv.className = 'message';messageDiv.innerHTML = `<div><span class="user-info">${data.userName} (ID: ${data.userId})</span><span class="timestamp">${data.timestamp}</span></div><div class="message-content">${data.message}</div>`;container.appendChild(messageDiv);});}function sendDataToParent() {const mockData = generateMockData();if (window.parent !== window) {window.parent.postMessage({type: 'mock_data',data: mockData,source: 'iframe'}, '*'); console.log('数据已发送到父页面:', mockData);alert('数据已成功发送到父页面!');} else {alert('当前页面不是iframe,无法发送数据到父页面');}}document.addEventListener('DOMContentLoaded', displayMockData);const sendButton = document.getElementById('send-btn');sendButton.addEventListener('click', sendDataToParent);</script></script>
</html>