React Native WebView postMessage 不起作用
Posted
技术标签:
【中文标题】React Native WebView postMessage 不起作用【英文标题】:React Native WebView postMessage does not work 【发布时间】:2017-04-30 19:45:35 【问题描述】:我无法让 React Native WebView postMessage 工作。 React Native 应用程序成功接收到来自 Web 应用程序的 post 消息。但是 Web 应用没有收到 React Native 应用发送的消息。
我的简单网络应用
<html>
<body>
<button>Send post message from web</button>
<div>Post message log</div>
<textarea style="height: 50%; width: 100%;" readonly></textarea>
<script>
var log = document.querySelector("textarea");
document.querySelector("button").onclick = function()
console.log("Send post message");
logMessage("Sending post message from web..");
window.postMessage("Post message from web", "*");
window.addEventListener("message", function(event)
console.log("Received post message", event);
logMessage(event.data);
, false);
function logMessage(message)
log.append((new Date()) + " " + message + "\n");
</script>
</body>
</html>
此网络应用托管在:https://popping-heat-6062.firebaseapp.com/
我的简单 React Native 应用
import React, Component from "react";
import AppRegistry, Text, View, TouchableHighlight, WebView from "react-native";
export default class WevViewApp extends Component
constructor( props )
super( props );
this.webView = null;
onMessage( event )
console.log( "On Message", event.nativeEvent.data );
sendPostMessage()
console.log( "Sending post message" );
this.webView.postMessage( "Post message from react native" );
render()
return (
<View style=flex: 1>
<TouchableHighlight style=padding: 10, backgroundColor: 'blue', marginTop: 20 onPress=() => this.sendPostMessage()>
<Text style=color: 'white'>Send post message from react native</Text>
</TouchableHighlight>
<WebView
style=flex: 1
source=uri: 'https://popping-heat-6062.firebaseapp.com'
ref=( webView ) => this.webView = webView
onMessage=this.onMessage
/>
</View>
);
AppRegistry.registerComponent( 'WevViewApp', () => WevViewApp );
预期结果
-
单击“从网络发送帖子”按钮发送
向 React Native 应用程序发布消息并在调试器中登录
窗口
单击“从 React Native 发送帖子”按钮
向 Web 应用程序发送帖子消息并在 Web 中打印出来
文本区域
实际结果
-
Web 应用成功向 React Native 应用发送消息并登录到调试器窗口
React Native 应用程序不成功向网络应用程序发送消息,并且未在网络文本区域中打印出来
有人知道为什么网络应用没有收到消息吗?
相关文档:https://facebook.github.io/react-native/docs/webview.html
编辑:经历了可能查明问题的行为。
当直接在网络浏览器中测试“从网络发送帖子”按钮时,textarea 会记录它已经发送了消息并且收到了它自己的消息。
Thu Dec 15 2016 10:20:34 GMT+0100 (CET) Sending post message from web..
Thu Dec 15 2016 10:20:34 GMT+0100 (CET) Post message from web
在 React Native 应用程序的 WebView 中尝试相同操作时,textarea 只会打印出来
Thu Dec 15 2016 10:20:34 GMT+0100 (CET) Sending post message from web..
WebView 是否劫持了 window.postMessage 方法并注入了自定义方法?
documentation中提到了这个:
设置此属性会将 postMessage 全局注入到您的 webview,但仍会调用 postMessage 的预先存在的值。
也许这是错误的,这就是问题所在?
【问题讨论】:
我也有同样的问题,花了一整天的时间寻找解决方法,但是没有,正在处理一个拉取请求,也许我们会得到一些解决方案。 github.com/facebook/react-native/pull/10941 【参考方案1】:我遇到了同样的问题,并通过将事件侦听器添加到文档而不是窗口来解决它。变化:
window.addEventListener("message", ...
到:
document.addEventListener("message", ...
【讨论】:
这行得通。谢谢。请记住,如果您还想支持常规浏览器,您应该同时定义document.addEventListener("message", ...
和 window.addEventListener("message", ...
。
谢谢,这对我很有帮助,节省了我不少时间,享受赏金吧。
谁能解释一下?
@YuriyChachora 因为它是这样实现的:github.com/facebook/react-native/blob/master/ReactAndroid/src/…
对于 iOS:github.com/facebook/react-native/blob/master/React/Views/…【参考方案2】:
react-native-webview changes how this behavior works 的第 5 版。你现在想要:
window.ReactNativeWebView.postMessage(data);
【讨论】:
成功了。聪明的答案:) 很好的答案。帮我解决了! 帮我解决了! 为我工作,非常感谢【参考方案3】:添加浏览器特定的事件监听器
在 Android 中
document.addEventListener("message", function(event)
alert("This is a Entry Point Working in Android");
init(event.data)
);
在 iOS 中
window.addEventListener("message", function(event)
alert("This is a Entry Point Working in iOS");
init(event.data)
);
【讨论】:
【参考方案4】:实际上,监听器在不同的操作系统(如 iOS 和 Android)中的工作方式不同。所以你应该使用 document.addEventListener for Android 和 window.addEventListener for iOS。
if(navigator.appVersion.includes('Android'))
document.addEventListener("message", function (data)
alert("you are in android OS");
);
else
window.addEventListener("message", function (data)
alert("you are in android OS");
);
【讨论】:
我认为这实际上是已发布答案的副本。如果您认为可以添加一些内容,那么最好提交对现有答案的编辑。【参考方案5】:您可以按照以下步骤操作 Pub/Sub =>>
第 1 步 => 在您的 React Native 应用程序中添加插件: https://github.com/react-native-webview/react-native-webview
第 2 步 => 在 ReactNative(Mobile Part) 中添加以下代码:
import React, Component from "react";
import SafeAreaView, Text, TouchableHighlight from "react-native";
import WebView from "react-native-webview";
class MobileWebView extends Component
state = ;
onMessage = event =>
const data = event.nativeEvent;
this.setState( data );
;
render()
return (
<SafeAreaView style= flex: 1 >
<TouchableHighlight
style=
padding: 10,
backgroundColor: "red",
width: "100%",
onPress=() =>
this.webview.postMessage("Message From React Native App to Web");
>
<Text>Send Message To Web</Text>
</TouchableHighlight>
<Text>Mobile: this.state.data</Text>
<WebView
ref=ref =>
this.webview = ref;
source= uri: "http://localhost:3000/"
onMessage=this.onMessage
style= flex: 1
/>
</SafeAreaView>
);
export default MobileWebView;
第 3 步 => 在 ReactJS(Web Part) 中添加以下代码:
import React, Component from "react";
class WebApp extends Component
state = ;
componentDidMount()
document.addEventListener("message", event =>
this.setState( msg: event.data );
);
window.addEventListener("message", event =>
this.setState( msg: event.data );
);
render()
return (
<div>
<div>Web: this.state.msg</div>
<button
onClick=() =>
window.ReactNativeWebView.postMessage(
"Post message from web to Mobile",
"*"
);
>
Send Message To React Native(Mobile)
</button>
</div>
);
export default WebApp;
一切顺利,现在您可以从移动设备向网络发送和接收消息,反之亦然。
Output Image
【讨论】:
【参考方案6】:以上答案均不适用于 IOS,可能仍适用于 android 设备。这种方式适用于所有平台 -
在原生反应中:
const generateOnMessageFunction = data =>
`(function()
window.WebViewBridge.onMessage($JSON.stringify(data));
)()`;
class RNScreen extends React.Component
private webView: RefObject<WebView> = createRef();
render()
return (
<WebView
javascriptEnabled
domStorageEnabled
bounces=false
ref=this.webView
onLoadEnd=() =>
this.postMessageTest(helloFromRN: true);
/>
)
private postMessageTest(data)
this.webView.current.injectJavaScript(generateOnMessageFunction(data));
在JS端-
window.WebViewBridge =
onMessage: this._onMessage,
;
const event = new Event('WebViewBridge');
window.dispatchEvent(event);
// The data is not a string. It is an object.
private _onMessage(data: Object)
// Should log "helloFromRN" on load.
console.log(data)
【讨论】:
以上是关于React Native WebView postMessage 不起作用的主要内容,如果未能解决你的问题,请参考以下文章
WebView(react-native-webview)在 Expo SDK36 中获取错误代码 -1
React Native开发React Native控件之WebView组件详解以及实例使用(22)