React Native中WebView与html双向通信遇到的坑

 更新时间:2023年01月29日 09:01:34   作者:流星雨在线  
这篇文章主要介绍了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自动完成搜索组件Turnstone实现示例

    可定制React自动完成搜索组件Turnstone实现示例

    这篇文章主要为大家介绍了可定制React自动完成搜索组件Turnstone实现示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-10-10
  • React Router 5.1.0使用useHistory做页面跳转导航的实现

    React Router 5.1.0使用useHistory做页面跳转导航的实现

    本文主要介绍了React Router 5.1.0使用useHistory做页面跳转导航的实现,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-11-11
  • React hooks如何清除定时器并验证效果

    React hooks如何清除定时器并验证效果

    在React中,通过自定义Hook useTimeHook实现定时器的启动与清除,在App组件中使用Clock组件展示当前时间,利用useEffect钩子在组件挂载时启动定时器,同时确保组件卸载时清除定时器,避免内存泄露,这种方式简化了状态管理和副作用的处理
    2024-10-10
  • React中hook函数与useState及useEffect的使用

    React中hook函数与useState及useEffect的使用

    这篇文章主要介绍了React中hook函数与useState及useEffect的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧
    2022-10-10
  • react无限滚动组件的实现示例

    react无限滚动组件的实现示例

    本文主要介绍了react无限滚动组件的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-05-05
  • React 高德地图进京证路线规划问题记录(汇总)

    React 高德地图进京证路线规划问题记录(汇总)

    这篇文章主要介绍了React高德地图进京证路线规划问题小记,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧
    2024-08-08
  • 在 React Native 中给第三方库打补丁的过程解析

    在 React Native 中给第三方库打补丁的过程解析

    这篇文章主要介绍了在 React Native 中给第三方库打补丁的过程解析,有时使用了某个React Native 第三方库,可是它有些问题,我们不得不修改它的源码,本文介绍如何修改源码又不会意外丢失修改结果的方法,需要的朋友可以参考下
    2022-08-08
  • react源码层深入刨析babel解析jsx实现

    react源码层深入刨析babel解析jsx实现

    同作为MVVM框架,React相比于Vue来讲,上手更需要JavaScript功底深厚一些,本系列将阅读React相关源码,从jsx -> VDom -> RDOM等一些列的过程,将会在本系列中一一讲解
    2022-10-10
  • ahooks正式发布React Hooks工具库

    ahooks正式发布React Hooks工具库

    这篇文章主要为大家介绍了ahooks正式发布值得拥有的React Hooks工具库使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-07-07
  • React Grid Layout基础使用示例教程

    React Grid Layout基础使用示例教程

    React Grid Layout是一个用于在React应用程序中创建可拖拽和可调整大小的网格布局的库,通过使用React Grid Layout,我们可以轻松地创建自适应的网格布局,并实现拖拽和调整大小的功能,本文介绍了React Grid Layout的基础使用方法,感兴趣的朋友一起看看吧
    2024-02-02

最新评论