React Native WebView postMessage不起作用

时间:2016-12-15 09:08:42

标签: javascript html5 webview react-native

我无法让React Native WebView postMessage工作。 React Native应用程序成功从Web应用程序接收post message messaget。但是,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 );

预期结果

  1. 点击“从网上发送帖子”按钮发送 发送到React Native应用程序的消息,并在调试器中登录 窗口
  2. 单击“从React Native发送邮件”按钮 将帖子消息发送到Web应用程序并在Web中打印出来 textarea的
  3. 实际结果

    1. 网络应用成功向React Native应用发送消息并在调试器窗口中记录
    2. React Native应用失败向网络应用发送消息,但未在网络文本区打印
    3. 有谁知道为什么网络应用没有收到消息?

      使用Android和iOS进行测试。

      相关文档: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的预先存在的值。

      也许这是错误的,这就是问题所在?

6 个答案:

答案 0 :(得分:42)

我遇到了同样的问题并通过将事件监听器添加到文档而不是窗口来修复它。变化:

window.addEventListener("message", ...

为:

document.addEventListener("message", ...

答案 1 :(得分:3)

react-native-webview changes how this behavior works的版本5。您现在想要:

window.ReactNativeWebView.postMessage(data);

答案 2 :(得分:2)

在Android系统中

nil

在iOS中

 document.addEventListener("message", function(event) {
       alert("This is a Entry Point Working in android");
       init(event.data)
  });

enter image description here

答案 3 :(得分:0)

实际上,侦听器在不同的操作系统(例如iOS和Android)中的工作方式有所不同。因此,对于Android,应使用document.addEventListener;对于iOS,应使用window.addEventListener。

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");               
             });
        }

答案 4 :(得分:0)

以上答案均不适用于 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)
}

答案 5 :(得分:0)

您可以按照以下步骤进行发布/订阅 =>>

步骤 1 => 在您的本机应用程序中添加插件: 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;

一切顺利,现在您可以从移动设备到 Web 发送和接收消息,反之亦然。

Output Image