【问题标题】:React Native WebView postMessage does not workReact Native WebView postMessage 不起作用
【发布时间】: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 );

预期结果

  1. 单击“从网络发送帖子”按钮发送 向 React Native 应用程序发布消息并在调试器中登录 窗口
  2. 单击“从 React Native 发送帖子”按钮 向 Web 应用程序发送帖子消息并在 Web 中打印出来 文本区域

实际结果

  1. Web 应用成功向 React Native 应用发送消息并登录到调试器窗口
  2. React Native 应用程序不成功向网络应用程序发送消息,并且未在网络文本区域中打印出来

有人知道为什么网络应用没有收到消息吗?

通过 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 的预先存在的值。

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

【问题讨论】:

标签: javascript html webview react-native


【解决方案1】:

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

window.addEventListener("message", ...

到:

document.addEventListener("message", ...

【讨论】:

【解决方案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)
      }
      

      【讨论】:

        猜你喜欢
        • 2020-07-03
        • 1970-01-01
        • 2021-09-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多