react-native-webview通讯设计

1,319 阅读1分钟

内嵌的 html 页面需要和 RN 底层进行通讯,主要用到 react-native-webview 的 window.ReactNativeWebView.postMessage、onMessage、injectJavaScript和html 中的 event 事件机制。

html 传值给 RN

VUE传值

<template>
    <button @click="handleClick">test1</button>
</template>
<script>
export default {
  name: 'App',
  methods:{
    handleClick(){
      window.ReactNativeWebView.postMessage('hello')
    }
  }
}
</script>

RN接收

const App = ()=>{
  function handleMessage(e){
    Alert.alert('提醒',e.nativeEvent.data)
  }
  return(
    <WebView
        onMessage={handleMessage}
      />
  )
}

RN传值给 html

传值的数据格式设置

  1. html=>RN

    {
      typeCode:'xxx', // 要调用的接口
      eventId: 'xxx-uuid',// 事件 id,唯一性,完成原生接口后回传数据
      option: {}//接口配置
      data: {} // 接口数据
    }
    
  2. RN=>html

    {
      code:'',// 执行结果的 code,成功或者失败
      error_msg: '',// 错误信息
      data: {}// 执行结果
    }
    

具体代码

  1. VUE 传值

    <template>
    <button @click="handleClick('camera')">test1</button>
    </template>
    <script>
    export default {
      name: 'App',
      methods:{
        handleClick(typeCode){
          this.postMessage(typeCode)
        },
        getOption(typeCode,options,data){ // 生成唯一事件 id 并返回组合好的配置
          const eventId = type+'-'+randomValue()
          return {
            typeCode,
            eventId,
            options,
            data
          }
        }
        postMessage(typeCode,options={},data={}){
          const config = getOption(typeCode,options,data)
          return new Promise((resolve,reject)=>{
            window.addEventListener(config.eventId,(e)=>{// 注册事件到 window 上面
              const response = e.detail
              if(response.code === 'success'){
                resolve(response)
                return
              }
              reject(new Error(response.error_message))
            },{
              once: true // 设置只允许触发一次,完成后自动移除
            })
            window.ReactNativeWebView.postMessage(JSON.stringify(config))
          })
        }
      }
    }
    </script>
    
  2. RN传值

    const App = ()=>{
      let view;
      function handleMessage(e){
        const config = JSON.preas(e.nativeEvent.data)
        handleOpenCamera(config)
      }
      function handleOpenCamera(config) {
        const data = await openCamra()
        sendMsgtToHtml(config.eventId,data)
      }
      // 注入 js 代码,触发注册好的事件
      function sendMsgtToHtml(eventId,info){
        const jsCode = `
          window.dispatchEvent(new CustomEvent('${eventId}',{'detail':{data:${JSON.stringify(
          info,
        )},code:'success'}}))
          true; // 最后的这个 true 必须设置
        `
        view.injectJavaScript(jsCode) // 通过注入代码的方式触发事件,回传数据
      }
      return(
        <WebView
            ref={(ref)=>view=ref}
            onMessage={handleMessage}
          />
      )
    }
    

小结

到这基本就完成了互相通讯的设计了,具体的一些细节还需要去补充,例如持续获取数据(监听移动轨迹),拍照获取照片和视频资源等;