跨窗口通信就是在嵌套了iframe
的时候,实现iframe
与父窗口的通信。
什么是iframe
html
标签,它可以将一个网站作为一个dom
元素,嵌入到另一个网站中。iframe
具有自己的window
与document
对象。使用场景
iframe
嵌入的方式。减少了重复开发的时间,需要修改界面的时候,也只需要修改一份代码即可。iframe
来实现。当两个网站同时满足:同协议+同域名+同端口的时候。
iframe
进行完全访问,如window
,document
,location
等对象的访问。iframe
的全局函数。iframe
的元素内容index1.html
嵌套同源的index2.html
html1
<body> <h1>html-1</h1> <iframe src="http://127.0.0.1:3000/index2.html" frameborder="0"></iframe> <script> const iframe = document.querySelector("iframe"); iframe.onload = function () { console.log(iframe) // 获取iframe的window对象 const iWindow = iframe.contentWindow; // 获取iframe的document对象 const iDocument = iframe.contentDocument; console.log(iWindow) console.log(iWindow.location) iWindow.say() iDocument.body.innerHTML = "<h1>this is html-1</h1>" } </script> </body>
html2
<body> <h1>html-2</h1> <script> function say() { console.log("saying!!!") } </script> </body>
效果图
index1.html
嵌套同源的index2.html
发现子iframe
的window
,document
,location
对象,以及子iframe
的全局方法都可以访问。
iframe
的window
的所有属性与方法。iframe
的document
。iframe
的全局方法。window.frames
:获取子iframe
的列表,与document.querySelector("iframe")
一样
window.parent
:获取父window
的引用
window.top
:获取最顶层窗口的window
引用
上一节我们讲到,当iframe
同源时,不同窗口可以拿到对方的window
对象,以及全局方法,那么我们可以利用全局方法来实现不同window
窗口的通信。
html1
<body> <h1>html-1</h1> <div> <button onclick="send(Math.random(1))">发送数据给html2</button> </div> <iframe src="http://127.0.0.1:3000/index2.html" frameborder="0"></iframe> <script> const iframe = document.querySelector("iframe"); let send; iframe.onload = function () { // 获取iframe的window对象 const iWindow = iframe.contentWindow; // 获取iframe的document对象 const iDocument = iframe.contentDocument; function receive(value) { console.log("这是html1,来了一条数据:", value) } send = function (value) { iWindow.receive(value) } } </script> </body>
html2
<body> <h1>html-2</h1> <div> <button onclick="send(Math.random(1))">发送数据给html1</button> </div> <script> function receive(value) { console.log("当前是html2,收到一条数据:", value) } function send(value) { window.parent.receive(value) } </script> </body>
同理,window.top也可以这样通信
postMessage
支持不同窗口之间的通信,即使是非同源的情况。
发送数据
当需要使用给其他窗口(window)发送数据时,需要调用对方window
的postMessage
方法。
该方法接收两个参数
接收数据
监听message
事件
该事件对象包含接收的数据,以及发送方的地址等信息。
html1
<body> <h1>html-1</h1> <div> <button onclick="send(Math.random(1))">发送数据给html2</button> </div> <iframe src="http://127.0.0.1:3001/index2.html" frameborder="0"></iframe> <script> const iframe = document.querySelector("iframe"); let send; iframe.onload = function () { // 获取iframe的window对象 const iWindow = iframe.contentWindow; send = function (value) { iWindow.postMessage("wuwuwuw", "http://127.0.0.1:3001") } } window.addEventListener("message", function (event) { if (event.origin != 'http://127.0.0.1:3001') { // 过滤指定地址的信息 return; } if (window == event.source) { // 页面初始化的时候会被浏览器触发一次message,在这里根据发送方地址进行过滤 return } console.log("html1收到的数据 " + event.data); }) </script> </body>
html2
<body> <h1>html-2</h1> <div> <button onclick="send(Math.random(1))">发送数据给html1</button> </div> <script> function receive(value) { console.log("当前是html2,收到一条数据:", value) } function send(value) { window.parent.postMessage(value, "http://127.0.0.1:3000") } window.addEventListener("message", function (event) { if (event.origin != 'http://127.0.0.1:3000') { // 过滤指定地址的信息 return; } if (window == event.source) { // 页面初始化的时候会被浏览器触发一次message,在这里根据发送方地址进行过滤 return; } console.log("html2收到的数据 " + event.data); }) </script> </body>
效果图