postMessage真香

一、什么是postMessage

postMessage是HTML5中新引入的API,它能够实现跨窗口以及跨域的通讯。postMessage相似与Ajax可是它不受同源策略的限制而且通讯双方都是客户端。javascript

二、postMessage相关API介绍

2.一、发送数据

语法:html

quoteWindow.postmessage(data, origin, [transfer])
复制代码

quoteWindow

其中quoteWindow表示其余窗口的一个引用,是被发送数据的一方(接收数据),能够是如下类型java

  1. iframe的contentWindow
<body>
    <iframe class="childIframe" scr="http://XXX:8080"></iframe>
    <script> // 获取iframe的contentWindow const win = document.querySelector('.childIframe').contentWindow </script>
</body>
复制代码
  1. 执行window.open()方法返回的对象
<body>
    <script> // 获取window.open()打开窗口的引用 const win = window.open('http://XXX:8888') </script>
</body>
复制代码
  1. 命名过或数值索引的window.frames
<body>
    <script> const iframes = window.frames </script>
</body>
复制代码

data

data表示发送的数据,在MDN中说到:data表示将要发送到其余 window的数据。它将会被结构化克隆算法序列化。这意味着你能够不受什么限制的将数据对象安全的传送给目标窗口而无需本身序列化。[1]算法

origin

经过origin能够指定哪些窗口能够接收到该消息事件,它的值能够是如下:跨域

  • "*"

表示不受限制安全

  • URL地址

表示只有该URL地址的窗口才能接收到消息。这个设计尤其重要,由于咱们在传输一些敏感信息的时候就须要指定窗口才能接收该事件,防止恶意攻击。app

transfer

是一串和message 同时传递的Transferable对象.这些对象的全部权将被转移给消息的接收方,而发送一方将再也不保有全部权。dom

总结一下函数

发送数据使用postMessage方法,要那个窗口发送数据就调用该窗口的postMessage的方法,并在方法中传入相关的参数。post

2.二、接收数据

语法

window.addEventListener('message', (e) => {
    // ...
})
复制代码

在须要接收消息的页面中监听一个**message**事件,当其余窗口发送数据后就会触发该事件,而后执行相应的事件函数。

在接收到的事件对象中有三个重要的属性

  1. origin;表示发送消息窗口的源,能够经过此属性判断源是否安全
  2. data;表示发送消息窗口发送的数据
  3. source;表示对发送消息窗口的引用,能够用此来向发送消息的窗口返回数据

三、具体使用

定义父窗口:

<body>
  <h1>This is parent window</h1>
  <input type="text" class="inp">
  <button class="send">发送信息到iframe</button>
  <div class="contents">
    <p>接收到的信息</p>
    <ul class="messages">

    </ul>
  </div>
  <iframe src="child.html" frameborder="3" class="child-iframe" height="600" width="800"></iframe>
  <script> // 父页面监听message事件,接受iframe发送的消息 window.addEventListener('message', e => { if (e.origin !== 'http://127.0.0.1:5500') { // 验证对方的身份 return } const box = document.querySelector('.messages') box.innerHTML += `<li> 收到新的信息:${e.data}, 来自于${e.origin}</li>`; }); // iframe的引用 const win = document.querySelector('.child-iframe').contentWindow document.querySelector('.send').addEventListener('click', () => { const msg = document.querySelector('.inp').value win.postMessage(msg, '*') // 这里使用*,也能够是iframe的URL地址 document.querySelector('.inp').value = '' }) </script>
</body>
复制代码

定义子窗口

<body>
  <h1>This is iframe child page</h1>
  <input type="text" class="inp">
  <button class="send">发送信息到夫窗口</button>
  <div class="contents">
    <p>接收到的信息</p>
    <ul class="messages">

    </ul>
  </div>
  <script> let parentWin // 监听父页面的消息 window.addEventListener('message', e => { if (e.origin !== 'http://127.0.0.1:5500') { // 验证对方的身份 return } // 发送详细窗口的window对象引用,调用对象postMessage方法实现父子页面的通讯,固然也可使用window.parent来通讯 parentWin = e.source const box = document.querySelector('.messages') box.innerHTML += `<li>接收到新的信息:${e.data}, 来自于${e.origin}</li>` }) console.log(window.parent.location) document.querySelector('.send').addEventListener('click', () => { const msg = document.querySelector('.inp').value window.parent.postMessage(msg, '*') //  document.querySelector('.inp').value = '' }) </script>
</body>
复制代码

这样就实现了父子窗口之间的通讯。以下图:

postMessage还能够实现跨域通讯等,后续继续研究。

四、修改iframe中DOM节点的样式

4.一、获取到元素后修改

window.onload = function () {
    let dom = document.getElementById('frame').contentWindow.document.getElementById('selector')
    // 修改style
    dom.style.color = "red"
    // 修改class
    dom.classList.add('box')
}
复制代码

4.二、在iframe的header中添加CSS样式

若是一个元素是动态添加的就获取不到该DOM因此能够经过添加CSS样式的方法。

let header = document.getElementById('frame').contentWindow.document.getElementById('header')
const CSS_STR = ` .box { color: red } `
const style = document.createElement('style')
style.innerText = CSS_STR
header.appendChild(style)
复制代码

五、兼容性

更多文章

相关文章
相关标签/搜索