前言

        最近一直在写RN的项目,该项目是一个移动端的项目,主要用来对设备进行控制和设置。其中有个模块涉及到使用WebView的方式嵌入H5页面,那么就需要熟悉RN与H5之间的通信。其实在此之前,我一直接触的是Hybrid APP的方式开发app,其中的基本框架也是原生使用webview的方式嵌入我们所写的前端H5页面。对于这个方式,我在之前的文章中也有总结过:Hybrid App(原生+H5)开发-CSDN博客。这篇文章,我主要是对这次项目使用RN与WebView通信的总结。

什么是WebView?

        webView是一种用于应用程序中显示web内容的组件,它可以嵌入到应用程序的用户界面中,以便显示网页、HTML内、网页表单等等。WebView提供了一个浏览器引擎,使应用程序能够加载和现实Web页面,并与页面进行交互。

WebView的使用场景

1.显示网页内容:通过加载URL或者HTML代码,可以在应用程序中展现网页、新闻、文章等内容。

2.内嵌第三方网页服务:有些应用需要继承第三方网页服务,例如社交媒体登录、支付接口等。WebView可以方便嵌入这些服务的网页,使用户能够在应用中进行操作

3.显示本地HTML文件:除了加载远程网页,WebView还可以加载本地的HTML文件,这对于需要在应用程序中展示静态内容或者离线内容的情况非常有用。

4.实现Hybrid应用:Hybrid应用是指将Web技术(如HTML、CSS、JavaScript)与原生应用程序结合起来的应用。WebView可以作为Hybrid应用的核心组件,用于显示Web页面,并通过与JavaScript原生代码进行交互。

5.加载本地资源:除了加载网页,WebView还可以加载应用程序中的其他资源,例如图片、CSS文件、JavaScript文件等。这样还可以实现更丰富的用户界面效果。

6.执行JavaScript操作:WebView可以执行JavaScript代码,可以通过此与网页交互。例如修改网页内容、获取网页元素、调用网页中的JavaScript函数等。

7.实现自定义浏览器:有些应用程序需要提供自定义的浏览器功能,例如添加书签、历史记录、搜索引擎等。通过WebView,开发人员可以实现这些功能,并根据自己的需求进行定制。

如何使用WebView

<WebView
  ref={view => (this.webView = view)}
  ...
  source={{ uri: `http://localhost:8000/index?systemLanguage=${this.state.systemLanguage}`, method: 'GET' }}
  ...
  onMessage={event => {
    this._onH5Message(event);
  }}
/>
  • source:加载资源URL,URL你可以自由拼接参数(下面会讲如何获取这个url参数)
  • ref:将WebView组件的引用保存到类组件的实力上,方便在其他地方调用它的方法。
  • onMessage:监听H5消息并响应

详细方法解析:

React Native

监听接收数据

_onH5Message接收来自H5的消息

_onH5Message = e => {
  const result = JSON.parse(e.nativeEvent.data);
  switch (result.type) {
    case 'queryAvgDayEnergyData': 
        this.energy_queryAvgDayEnergyData_all(query); 
        break;
    case 'queryHourDatas':
        this.temp_queryFinish_hour_all(query);
        break;
    ...
  }
}

通过webview的onMessage方法监听来自嵌入H5的请求,按照类型分发到不同的处理函数。

同时,在下面的处理函数中,会把请求到的数通过reactSendMessage方法传给H5即webview页面

  async temp_queryFinish_dayAndYear_all(query) {
    let result = [];
    const _this = this;
    const params = {
      devId: this.props.devInfo.devId,
      startDay: query.start,
      endDay: query.end,
      // ....
    };
    Promise.all([
      TYSdk.apiRequest('请求涂鸦URL', { ...params, dpId: 107 }, '2.0'),
      TYSdk.apiRequest('请求涂鸦URL', { ...params, dpId: 108 }, '2.0'),
    ])
      .then(([data1, data2]) => {
        result = [data1, data2];
        // .....
        // 获取请求数据后,马上注入webView中
        _this.sendToHTML({
          type: 'queryAvgDayEnergyData',
          data: JSON.stringify(_this.state.temp_queryFinish),
        });
      })
      .catch(error => {
        TYSdk.mobile.hideLoading();
        // 异常处理...
      });
  }
     

向WebView发送数据

这个方法中有一个关键的额方法,就是sendToHTML,这个方法就是像H5发送数据

sendToHTML = ({ type, data }) => {
  this.webView.injectJavaScript(`reactSendMessage('{"type": "${type}","data": ${data}}');`);
}

通过this.webView获取webview实例,同时调用注入的JS函数reactSendMessage向web页面发送数据。

WebView

接收数据

WebView页面这里用的框架式vue

mounted() {
  // web端接受数据:RN -> H5
  window.reactSendMessage = this.reactSendMessage;
}

这里是WebView与React Native交互的关键代码:RN通过reactSendMessage(data)来给H5页面传数据。也就是说,H5页面暴露了一个接口reactSendMessage,RN会调用它并传递数据。

所以在H5的reactSendMessage方法中,可以针对RN发送过来的数据进行一些数据处理

methods: {
  reactSendMessage(data) {
    const parsed = JSON.parse(data);
    switch (result.type) {
        case "queryAvgDayEnergyData":
            //this.queryAvgDayEnergyData= result.data;
            this.handleDayData(result.data);
            break;
        case "queryAvgHourEnergyData":
            //this.queryAvgHourEnergyData= result.data;
            this.handleHourData(result.data);
            break;
        ....
        default:
            break;
    }
  }
}

向RN发送数据

methods() {
  //处理数据
  handleHourData(data){
    this.hourData = data
    // 数据格式化处理....
    //.....
    if (!this.hourData.length) {
       window.postMessage(
         JSON.stringify({
         type: "queryAvgDayEnergyData"
       })
    }else{
        let dataList = this.queryAvgDayEnergyDataFinish;
        // 处理数据,显示...
    }
  }
}

这里,在H5 WebView页面中,使用window.postMessage像RN发送数据,在RN中可以使用onMessage时间监听WebView发送过来的数据。与此同时,当两者有多重类型的数据传输时,需要定好相对应的key或者协议,使得接收和发送之间的数据都能一一对应上,进而进行不同的数据显示。比如我这里用的是type,不同的数据类型,使用不同的type去一一映射。

总结

React Native

  • 主要使用onMessage事件监听WebView发送过来的数据,这里定义为_onH5Message=(e)=>{}方法
  • 在_onH5Message方法中,根据定好的type的值,针对WebView返回的不同type值以及参数,去请求涂鸦相对应的接口数据
  • 将涂鸦响应数据以 injectJavaScript的方式注入WebView中,其中injectJavaScript是WebView的一个方法:this.webView.injectJavaScript

WebView

  • 首先在页面挂载的时候注册RN使用injectJavaScript注入的数据:window.reactSendMessage = this.reactSendMessage,其中this.reactSendMessage是H5这边定义的方法,参数则是RN传过来的JSON数据
  • 在reactSendMessage(data)方法中,解析JSON数据,根据定义好的不同type,解析不同类型的数据以显示页面
  • 同时,在处理显示数据的同时,有些时候需要考虑异常情况,所以在WebView中多了一步,判断数据为空的情况。为空的时候会以window.postMessage的方式向RN发起数据(携带type以及请求参数),RN根据WebView发送过来的数据,进而再想服务端发起请求,得到响应数据之后再以this.webView.injectJavaScript方式注入WebView中...(回到上面的步骤)

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐