問題:
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進行監聽的,需要關注消息來源,否則如果有多個同類型不同類型的消息,很容易引起監聽的沖突混淆
針對消息的發送,三種類型各不相同,但是多個同類型之間需要做好區分,否則依然有沖突混淆的問題