React Native中WebView與html雙向通信遇到的坑
安卓、ios原生與html雙向通信相對簡單且成熟,但是React Native與html的雙向通信存在那么一丟丟的坑
一、參數(shù)配置
導(dǎo)包
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)}})();`}
相關(guān)回調(diào)函數(shù)
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不能監(jiān)聽問題
注意:這里安卓用document,ios用window,否則會出現(xiàn)react-native-webview使用postMessage后H5不能監(jiān)聽問題
/* 監(jiān)聽rn消息 */ const eventListener = nativeEvent => { //解析數(shù)據(jù)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監(jiān)聽不到的問題
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監(jiān)聽不到的問題
三、React Native與html雙向通信
3.1、RN發(fā)數(shù)據(jù)到WebView
RN通過postMessage發(fā)送數(shù)據(jù)
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接受數(shù)據(jù)
/* 監(jiān)聽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發(fā)數(shù)據(jù)到RN
WebView通過postMessage發(fā)送數(shù)據(jù)
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 () { /* 監(jiān)聽rn消息 ------------------------------------------------------------------------------------------------------------- */ const eventListener = nativeEvent => { const {actionType, extra} = nativeEvent.data && JSON.parse(nativeEvent.data) || {} } //安卓用document,ios用window window.addEventListener('message', eventListener); document.addEventListener('message', eventListener); /* 發(fā)消息給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> `
到此這篇關(guān)于React Native中WebView與html雙向通信遇到的坑的文章就介紹到這了,更多相關(guān)React WebView與html雙向通信內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
React中實現(xiàn)編輯框自動獲取焦點與失焦更新功能
在React應(yīng)用中,編輯框的焦點控制和數(shù)據(jù)回填是一個常見需求,本文將介紹如何使用useRef和useEffect鉤子,在組件中實現(xiàn)輸入框自動獲取焦點及失焦后更新數(shù)據(jù)的功能,文中通過代碼示例給大家講解的非常詳細,需要的朋友可以參考下2024-01-01React Native中實現(xiàn)動態(tài)導(dǎo)入的示例代碼
隨著業(yè)務(wù)的發(fā)展,每一個 React Native 應(yīng)用的代碼數(shù)量都在不斷增加。作為一個前端想到的方案自然就是動態(tài)導(dǎo)入(Dynamic import)了,本文介紹了React Native中實現(xiàn)動態(tài)導(dǎo)入的示例代碼,需要的可以參考一下2022-06-06React性能優(yōu)化系列之減少props改變的實現(xiàn)方法
這篇文章主要介紹了React性能優(yōu)化系列之減少props改變的實現(xiàn)方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2019-01-01react-native android狀態(tài)欄的實現(xiàn)
這篇文章主要介紹了react-native android狀態(tài)欄的實現(xiàn),使狀態(tài)欄顏色與App顏色一致,使用戶界面更加整體。小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-06-06React?Hook中的useState函數(shù)的詳細解析
Hook 就是 JavaScript 函數(shù),這個函數(shù)可以幫助你鉤入(hook into) React State以及生命周期等特性,這篇文章主要介紹了React?Hook?useState函數(shù)的詳細解析的相關(guān)資料,需要的朋友可以參考下2022-10-10