iframe的使用和 contentWindow、parent以及postMessage通信方式

 

问题:

1. 如何进行消息通信(父发给子,子接收父的消息,也可父直接调用子的方法; 子发给父,父接收子的消息;)

2. 如何找到指定的子或者父window(如果iframe层级过多),又如何在发送消息时不影响其他的message监听

 

 

一、iframe的使用

<iframe 
style={{border:0,width:"100%",height:630,}} 
src={src}
/>

 

1. 如何进行消息通信(父发给子,子接收父的消息; 子发给父,父接收子的消息)

方法一: 直接通过获取父或者子的window来操作 (限制: 必须同域)

// 父调用子的方法:
 this.iframe.contentWindow.iframe的属性方法
//
document.getElementById("myIframe").contentWindow.iframe的属性方法

// 子调用父的方法:通过parent直接获取父的window
parent.document...

 

方法二:通过postMessage进行通信(限制: 需要父子约定)

// 父监听子消息:
window.addEventListener("message", () => this.listenFunc());

// 子发给父消息: 可通过window的属性找到对应的父(这里的parent表示直接上一级的父)
parent.postMessage(data, "*");  


// 父给子发消息
document.getElementById("iframe").contentWindow.postMessage(JSON.stringify(data), "*")

// 子监听父的消息
window.addEventListener("message", () => this.listenFunc());

 

 

2. 如何找到指定的子或者父window(如果iframe层级过多),又如何在发送消息时不影响其他的message监听

while(true) {
    // 判断,找到要找的父window,可以通过在父的window上绑定属性来实现
  if(currentWindow.isParent = true) {  
    currentWindow.postMessage(data, "*")
  }

  if(currentWindow == window.top) {
    break;  // 防止死循环
  } else {
    currentWindow = currentWindwo.parent;
  }
}

 

3. origin是否有用

 event.origin 可以获取当前消息的来源路径,通过判断当前iframe的url,判断是否是指定页面的消息来源

 

二、React Native的WebView和子内容的通信

// RN的WebView
<WebView
    ref={ref => this.webview = ref}
    source={{uri: ...}}
    javaScriptEnabled={true}
    onMessage={this.handleMassage}
    allowFileAccess={true}
    onLoadStart={}
    onLoadEnd={}
/>

1. 监听接收web(子)发送的消息

// 接收web发送的消息
handleMessage(event) {
  const data = JSON.parse(event.nativeEvent.data);
  const code = data.code;
  const msg = data.msg;
  switch(code) {
    case 0:
      console.log(msg);
      break;
  }
}

2. web(子)发消息给react native

// web发消息给react native
const data = {code: code, msg: msg};
window.ReactNativeWebView.postMessage(JSON.stringify(data));

3. React Native(父)发送消息给web(子)

// 发送消息给web
sendMessageToWebView(code, msg) {
  const data = {code: code, msg: msg};
  if(this.webview) {
    this.webview.postMessage(JSON.stringify(data));
  } else {
    console.log("no webview ref")
  }
}

4. web(子)对React Native(父)消息的监听

// web监听react native的postMessage消息,必须有document, 否则监听不到消息
window.document.addEventListener("message", this.onMessageListener.bind(this));

onMessageListener(event) {
    const data = JSON.parse(event.data);
    const code = data.code;
    const msg = data.msg;
    switch(code) {
        case ...
    }
}

 

 

三、 android的webview和包含内容的通信(仅做简单介绍)

agentWeb 相对于webview的使用

android 中可以定义当前的window下的名称,

web可以使用 类似window.WebAppInterface.onPostMessage(JSON.stringify(data))来发消息,WebAppInterface需要在Android中定义

 

 

综上: 

web的iframe之间,web和RN的webview之间,web和android之间的通信,都是使用message进行监听的,需要关注消息来源,否则如果有多个同类型不同类型的消息,很容易引起监听的冲突混淆

针对消息的发送,三种类型各不相同,但是多个同类型之间需要做好区分,否则依然有冲突混淆的问题

 

posted @ 2020-05-17 21:10  南歌子  阅读(7890)  评论(0编辑  收藏  举报