当前位置: 首页 > Web前端 > HTML5

react-native中webview的通信桥梁:ird-RnBridge

时间:2023-04-05 16:51:44 HTML5

背景介绍:前段时间研究了react-native中webview的通信机制,了解了其中的原理。刚在业务中遇到rn中的webview嵌入h5页面,发现虽然rn提供了类似js的postmessage机制,但是依赖这种机制在h5与rn的通信中往往很难提高开发效率和降低代码复杂度独自的。因此,基于提高在rn中开发h5的效率的原因,开发了这个ird-RnBridge。版本迭代历史简介:此桥主要适用于react-native和h5的通信场景,提供了rn端和h5端一套不同的api方法集进行调用。提供了几个功能:1)安全验证搭建桥梁:由于rn的很多原生功能都是通过webview提供给h5页面调用的,如果不去识别webview嵌入的h5页面是否安全,可以直接全部提供,这会带来很多安全问题。因此,rnbridge采用了双重验证的方式:首先:h5端必须调用checkSafety发起网桥建立请求,rn会对其发送的请求进行验证,验证交给rn端??处理。如果处理通过,rnbridge会向h5端发送一个token值,表示桥建立成功;其次:h5和rn的每一次通信都会携带token值,rnbridge会在rn端进行匹配,不一致则禁止调用。h5端:RnBridge.checkSafety({demo:'demo'},(data)=>{document.getElementById('demo').style.color='blue';console.log('bridgesuccess:',data);RnBridge.getSessionStore(['sat2'],(data)=>{constcontent=document.getElementById('content');content.innerText=JSON.stringify(data);console.log('data1',data);})});rn端:RnBridge.initWebview(this.webview,{checkSafety:(params,send)=>{this.veritySafety(params,send);},});veritySafety(params,send){send({isSuccess:true,result:'welcome'});}如果没有定义checksafeCheck,rnbridge自动认为通过,从而自动建立网桥。2)rn端和h5端相互通信:rn端可以通过initWebview注册提供给h5端的一组api方法。当桥建立后,rnbridge会将在initWebview中注册的一组方法名发送给h5端,h5端只需要直接调用invokeRN即可调用rn端的方法。rn端也是如此。3)提供方便的调试方式:因为h5是嵌入在rn的webview中的,h5中的ajax和console只能通过vconsole插件看到,调试不是很方便。所以rnbridge提供了debug方法,提供了console和ajax两种模式,可以直接在浏览器上直接查看和调试h5中的ajax和console。console:ajax:4)提供h5侧载资源的性能参数:可以通过sendPerformance和sendPerformanceByType发起webview加载h5、在h5和rn之间建立桥接等参数,最终可以得到h5的资源性能参数在rn层。加载性能参数:资源性能参数:原理介绍:这里简单介绍一下rnbridge的一些设计原理:建立桥和相互通信:安全验证,建立桥:h5调用rn方法:rn调用h5方法:应用介绍:因为rnbridge在rn端和h5端分别有一组api方法集,所以在调用这些方法之前,需要调用rnbridge的switchMode方法选择对应的一组api方法集;例如,在h5端:RnBridge.switchMode({mode:'h5'});此时h5的api集会被注入到window.RnBridge中,这样就可以在全局范围内自由调用了。在rn侧:RnBridge.switchMode({mode:'rn'});这时候rn的api集会被注入到RnBridge本身,所以可以通过RnBridge来调用。这是一个简单的例子:h5侧:RnBridge.switchMode({mode:'h5'});RnBridge.initH5({h1:(params,send)=>{send({isSuccess:true,result:{a2:39}});},h2:(params,send)=>{send({isSuccess:false,结果:{a1:21}});}});RnBridge.checkSafety({demo:'demo'},(data)=>{document.getElementById('demo').style.color='blue';});RnBridge.invokeRN({method:'a1',params:{a1:12},success:(result)=>{document.getElementById('demo').style.color='green';document.getElementById('demo').innerText=JSON.stringify(result);},失败:(result)=>{document.getElementById('demo').style.color='red';document.getElementById('demo').innerText=JSON.stringify(result);}});rn侧:RnBridge.switchMode({mode:'rn'});exportclassDemoextendsReact.Component{constructor(props){super(props);this.webview=null;}render(){return(<视图样式le={{flex:1}}>this.webview=ele}onMessage={(e)=>{console.log('e',e.nativeEvent.data);RnBridge.listenH5(e.nativeEvent.data);}}onError={(e)=>{console.log('error',e)}}onLoadEnd={()=>{console.log('loadend')}}onLoadStart={()=>{console.log('loadstart')}}/>{this.handleC()}}>点击)}componentDidMount(){console.log('RnBridge',RnBridge);RnBridge.initWebview(this.webview,{a1:(params,send)=>{this.handleA(params,send);},a2:(params,send)=>{this.handleB(params,send);},checkSafety:(params,send)=>{this.veritySafety(params,send);},setTitle:(params,send)=>{console.log('title',params);}})}veritySafety(params,send){send({isSuccess:true,result:'welcome'});}handleA(params,send){console.log(params);发送({isSuccess:false,result:'asdf'})}handleB(params,send){console.log(params);RnBridge.invokeH5({});setTimeout(()=>{send({isSuccess:true,result:'ok'})},1000);}handleC(){RnBridge.invokeH5({method:'h3',params:{demo:true},success:(params)=>{console.log('params',params);},fail:(params)=>{控制台。log('fail',params);}})}}详细的适用介绍可以看这里:ird-rnbridge'sreadmeend:这个工具库是利用我晚上加班后的休息时间设计开发的,所以rnbridge可能会有一些不足之处,如有不足请指出,我会利用业余时间继续优化迭代功能;开源不易,有可能,互相鼓励,如果觉得勉强还行,请在github点个星号鼓励一下