React Native中WebView与html双向通信遇到的坑
安卓、ios原生与html双向通信相对简单且成熟,但是React Native与html的双向通信存在那么一丢丢的坑
一、参数配置
导包
import {<!--{cke_protected}{C}%3C!%2D%2D%20%2D%2D%3E--> WebView } from 'react-native-webview'
使用
<WebView ref={ref => this.webViewRef = ref} source={{ uri: url }} // source={{ html }} javaScriptEnabled useWebKit allowFileAccess startInLoadingState onLoadStart={this.onLoadStart} onError={this.onError} onLoad={this.onLoad} onLoadEnd={this.onLoadEnd} renderLoading={this.renderLoading} renderError={this.renderError} javaScriptCanOpenWindowsAutomatically onMessage={this.handleMessage} injectedJavaScript={`(function() {window.postMessage = function(data) {window.ReactNativeWebView.postMessage(data)}})();`}
相关回调函数
onLoadStart = ({ nativeEvent }) => { console.log('onLoadStart', nativeEvent) } onError = ({ nativeEvent }) => { console.log('onError', nativeEvent) } onLoad = ({ nativeEvent }) => { this.setState({ title: nativeEvent.title }) console.log('onLoad', nativeEvent) } onLoadEnd = ({ nativeEvent }) => { console.log('onLoadEnd', nativeEvent) } renderLoading = () => { console.log('renderLoading') } renderError = ({ nativeEvent }) => { console.log('renderError', nativeEvent) } handleMessage = async ({ nativeEvent }) => { const { actionType, extra } = nativeEvent.data && JSON.parse(nativeEvent.data) || {} }
二、坑点
react-native-webview使用postMessage后H5不能监听问题
注意:这里安卓用document,ios用window,否则会出现react-native-webview使用postMessage后H5不能监听问题
/* 监听rn消息 */ const eventListener = nativeEvent => { //解析数据actionType、extra const {actionType, extra} = nativeEvent.data && JSON.parse(nativeEvent.data) || {} } //安卓用document,ios用window window.addEventListener('message', eventListener); document.addEventListener('message', eventListener);
RN的webview的onMessage监听不到的问题
injectedJavaScript={<!--{cke_protected}{C}%3C!%2D%2D%20%2D%2D%3E-->`(function() {window.postMessage = function(data) {window.ReactNativeWebView.postMessage(data)}})();`}
注意这里要加上injectedJavaScript,它重写window.postMessage方法解决了RN的webview的onMessage监听不到的问题
三、React Native与html双向通信
3.1、RN发数据到WebView
RN通过postMessage发送数据
const temp = { actionType: 'takePhoto', extra: { fileId: '1522501682737836034', fileUrl: 'https://gongbao-phoenix.oss-cn-hangzhou.aliyuncs.com/test/330100/1/2022/05/06/2efb943b439146ed86db0ad920c7edaf.jpg', originalFileName: 'E91FDC71-FD9C-49B9-B038-529C9CDC149B.jpg', tag: 'not_use', unionId: 'f143153ed07a428fa6308d6f73b1a2b9', }, } this.webViewRef.postMessage(JSON.stringify(temp))
webView接受数据
/* 监听rn消息 */ const eventListener = nativeEvent => { const {actionType, extra} = nativeEvent.data && JSON.parse(nativeEvent.data) || {} } //安卓用document,ios用window window.addEventListener('message', eventListener); document.addEventListener('message', eventListener);
3.2、WebView发数据到RN
WebView通过postMessage发送数据
const action = { actionType: 'viewPicture', extra: { pics: ['https://tva1.sinaimg.cn/large/e6c9d24ely1h0svk2jlcej20ps11ewld.jpg'], defaultIndex: 0, }, } window.postMessage(JSON.stringify(action));
RN注册onMessage接收
onMessage={<!--{cke_protected}{C}%3C!%2D%2D%20%2D%2D%3E-->this.handleMessage}
handleMessage = async ({ nativeEvent }) => { const { actionType, extra } = nativeEvent.data && JSON.parse(nativeEvent.data) || {} }
四、demo源码
import React, { Component } from 'react' import { DeviceEventEmitter, StyleSheet, } from 'react-native' import { WebView } from 'react-native-webview' import NavigatorBar from '../../components/NavigatorBar' import { SafeAreaView } from '../../components' export default class WebViewPage extends Component { state = { title: '', showBackAction: false, } _autoCheckNavigationBar = nativeEvent => { const { canGoBack } = nativeEvent this.setState({ showBackAction: canGoBack }) DeviceEventEmitter.emit('showTabBar', !canGoBack) } onLoadStart = ({ nativeEvent }) => { console.log('onLoadStart', nativeEvent) } onError = ({ nativeEvent }) => { console.log('onError', nativeEvent) } onLoad = ({ nativeEvent }) => { this.setState({ title: nativeEvent.title }) console.log('onLoad', nativeEvent) } onLoadEnd = ({ nativeEvent }) => { console.log('onLoadEnd', nativeEvent) this._autoCheckNavigationBar(nativeEvent) } renderLoading = () => { console.log('renderLoading') } renderError = ({ nativeEvent }) => { console.log('renderError', nativeEvent) } handleMessage = async ({ nativeEvent }) => { const { actionType, extra } = nativeEvent.data && JSON.parse(nativeEvent.data) || {} } render() { const { showBackAction } = this.state const { url } = this.props || {} return ( <SafeAreaView style={styles.container} hideBottomView={!showBackAction}> <NavigatorBar backAction={showBackAction && this.webViewRef.goBack} title={this.state.title} /> <WebView ref={ref => this.webViewRef = ref} // source={{ uri: url }} source={{ html }} javaScriptEnabled useWebKit allowFileAccess startInLoadingState onLoadStart={this.onLoadStart} onError={this.onError} onLoad={this.onLoad} onLoadEnd={this.onLoadEnd} renderLoading={this.renderLoading} renderError={this.renderError} javaScriptCanOpenWindowsAutomatically onMessage={this.handleMessage} injectedJavaScript={`(function() {window.postMessage = function(data) {window.ReactNativeWebView.postMessage(data)}})();`} /> </SafeAreaView> ) } } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#F5FCFF', }, }) const html = ` <!DOCTYPE html> <html lang="en"> <head> <title>测试页面</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <div style="text-align: center"> <button id="viewPicture">1,viewPicture</button> <p style="text-align: center">receive react native data: <span id="data"></span></p> </div> <script> window.onload = function () { /* 监听rn消息 ------------------------------------------------------------------------------------------------------------- */ const eventListener = nativeEvent => { const {actionType, extra} = nativeEvent.data && JSON.parse(nativeEvent.data) || {} } //安卓用document,ios用window window.addEventListener('message', eventListener); document.addEventListener('message', eventListener); /* 发消息给rn ------------------------------------------------------------------------------------------------------------- */ // 1、查看大图 document.getElementById('viewPicture').onclick = function () { const action = { actionType: 'viewPicture', extra: { pics: ['https://tva1.sinaimg.cn/large/e6c9d24ely1h0svk2jlcej20ps11ewld.jpg'], defaultIndex: 0, }, } window.postMessage(JSON.stringify(action)); } } </script> </body> </html> `
到此这篇关于React Native中WebView与html双向通信遇到的坑的文章就介绍到这了,更多相关React WebView与html双向通信内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
React Router 5.1.0使用useHistory做页面跳转导航的实现
本文主要介绍了React Router 5.1.0使用useHistory做页面跳转导航的实现,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下2021-11-11React中hook函数与useState及useEffect的使用
这篇文章主要介绍了React中hook函数与useState及useEffect的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧2022-10-10
最新评论