天天看點

H5頁面跨視窗通信之postMessage(iframe子頁面向父頁面發送資訊)

需求背景

    最近在做H5項目時,遇到一個需求,公司所有的項目共用了一個防人機頁面,當人機驗證完成時需要把結果參數發送給調用它的父頁面,APP端在使用驗證頁面時,結果是通過H5與APP互動方法傳遞的;但是H5引用這個頁面時,隻能通過iframe内嵌的方式來實作,這樣在驗證通過後就面臨着iframe内嵌頁面需要将驗證結果發送給外部父頁面,通知外部父頁面做相應的處理;

實作方式

    1.父頁面發送消息,子頁面接受消息

        父頁面:

<!-- a.index.html -->
<h1>父頁面</h1>
<iframe id="iframe" src="http://b.index.com"></iframe>
           
const iFrame = document.getElementById('iframe')
<!-- 需要等到iframe中的子頁面加載完成後才發送消息,否則子頁面接收不到消息 -->
iFrame.onload = function(){
  <!-- iFrame.contentWindow擷取到iframe的window對象 -->
  iFrame.contentWindow.postMessage('父頁面發送的消息','http://b.index.com');
}
           

        子頁面:

//有發送就有接收,與postMessage配套使用的就是message事件
window.addEventListener('message',e=>{
    <!-- 對消息來源origin做一下過濾,避免接收到非法域名的消息導緻的xss攻擊 -->
    if(e.origin==='http://a.index.com'){
        console.log(e.origin) //父頁面URL,這裡是http://a.index.com
        console.log(e.source) // 父頁面window對象,全等于window.parent/window.top
        console.log(e.data)  //父頁面發送的消息
    }
},false)
           

    2.子頁面發送消息,父頁面接受消息  

        子頁面:

window.parent.postMessage('子頁面發送的消息','http://a.index.com')
           

        父頁面:

window.addEventListener('message',e=>{
    <!-- 對消息來源origin做一下過濾,避免接收到非法域名的消息導緻的xss攻擊 -->
    if(e.origin==='http://b.index.com'){
        console.log(e.origin) //子頁面URL,這裡是http://b.index.com
        console.log(e.source) // 子頁面window對象,全等于iframe.contentWindow
        console.log(e.data) //子頁面發送的消息
    }
},false)
           

注意:

  • window.postMessage中的window指的是你想發送跨域消息的那個視窗(你需要通信的目标視窗),而不是自身視窗的window
    • 父頁面中:父頁面向子頁面發送跨域資訊,window就是在父頁面中嵌入的iframe指向的子頁面的window,即:iFrame.contentWindow
    • 子頁面中:子頁面想父頁面發送跨域資訊,window就是父頁面的window,在這裡因為子頁面是嵌入到父頁面中的,對于子頁面來講,window就是top或者parent
  • 需要等到iframe中的子頁面加載完成後才發送消息,否則子頁面接收不到消息
  • 在監聽message事件時需要判斷一下消息來源origin

最後附送父頁面檢測到子頁面發送的消息後,調用iframe子頁面自重新整理方法:

父頁面:

window.addEventListener("message", e => {
      if (e.data && e.data.verifData) {
        //調用子頁面自重新整理
        e.source.location.reload(true)
      }
    }, false)
           

繼續閱讀