浅谈React Native 传参的几种方式(小结)
在ReactNative中由于业务的需要,我们往往要在诸多的页面间,组件之间做一些参数的传递与管理,在这里我总结了几大经过验证,稳定好用的方式给大家
ReactNavigation导航传值
推荐指数:♥♥♥♥♥
适用范围:相互跳转的页面间传值
兼容性:IOS/Android
原理:ReactNavigation为页面的props上挂载了navigation对象,可用来做路由跳转,在做页面跳转时可以携带参数/回调方法前往目标页面,从而达到传参的目的
说明:这是官方推荐,也是我们在业务开发中用得最多,最为推崇的一种传参方式,思想与web在querystring上带参跳转类似,只是实现方式略微不同,举例
导航传值即可正向传值,也可反向传值例如A->B是正向传值,而B->A则是反向传值
正向传值:
A页面跳转向B页面,在组件内通过访问this.props.navigation.navigate('B',{
type:'list', callback:data=>{console.log('dataincallback:',data);} });
在B页面就能在组件的生命周期函数中拿到值
componentWillMount(){ const{state:{params:{type,callback},goBack}}=this.props.navigation; console.log('type:',type); //type'list' }
反向传值:在反回上一个页面时,手动调用callback,并给其传参,再调用goBack方法,即可达到目的
还是上面的例子:
当从B返回A的时候
goBackToPageA:()=>{ const{state:{params:{type,callback},goBack}}=this.props.navigation; callback({id:'123',message:type+'really?'}); goBack(); } goBackToPageA();
回到A页面后
'dataincallback:',{id:'123',message:'listreally?'});
也即callBack中的data参数就是{id:'123',message:'listreally?'}
DeviceEventEmitter触发事件并传值
推荐指数:♥♥♥♥
适用范围:页面间传值/组件间传值
兼容性:IOS/Android
原理:利用ReactNative包中提供的DeviceEventEmitter模块订阅事件,触发事件,并能同时传值
说明:DeviceEventEmitter从名字就能知道他是基于事件订阅的机制来进行传值的,当订阅某种事件后,触发的时候会调用订阅事件的回调,并能把值传送过去,并且在同页面内的组间件,不同页面间都可以传值,但前提是页面还未被销毁(销毁后事件的订阅会取消),例如:
DeviceEventEmitter.addListener('warning_event',(data)=>{console.log('data:',data);}) DeviceEventEmitter.emit('warning_event',{name:'MegaGalaxy'}); //data:{name:'MegaGalaxy'}
在emit(触发)事件后,回调函数的入参就变成了我们所传递的{name:'MegaGalaxy'},
也可不传值,不传值时callback的入参就是undefined
缺点:本质是对自定义事件的监听与触发,当页面逻辑复杂时,代码会相对变大,维护成本变高,且监听过多会造成性能问题,还有一点就是在页面销毁时必须移除监听:如果忘记移除监听会怎么样?那emit一次的时候,会多响应一次你加上去的监听
componentDidMount(){ this.eventHandler=DeviceEventEmitter.addListner('event_name',callback); } componentWillUnmount(){ this.eventHandler.remove(); }
个人建议:在梳理清楚页面逻辑后,合理使用
AsyncStorageKey-Value式的存储传参
推荐指数:♥♥♥♥
适用范围:跨页面跨组件的任性传参
兼容性:IOS/Android
原理:利用类似web中localStorage的思想,将参数/数据存放在AsyncStorage中,在需要的地方再取出来
说明:localStorage在web中的实用性与受欢迎程度大家是知道的,AsyncStorage其实就是rn版的localStorage,略微不同的是它是异步的,只返回Promise,所以与async/await结合会非常好用
···
在A页面
saveOrderData=async()=>{ try{ constorderData=[{id:1,data:[]},{id:2,data:[]}] awaitAsyncStorage.setItem('Order_data_cache',JSON.stringify(orderData)); }catch(error){ //Errorsavingdata } }
在B页面
loadOrderData=async()=>{ const__orderData=awaitAsyncStorage.getItem('Order_data_cache'); constorderData=JSON.parse(__orderData); this.setState({orderData}); }
缺点:以Key-Value式的存储传参,可能重点还是在数据存储上,且因为涉及到I/O的操作,在部份低端机型上,有卡顿的可能性
ReactContextApi传参(新版ContextApi)
推荐指数:♥♥♥
适用范围:不同页面间的组件共享公共类的数据
兼容性:IOS/Android
原理:利用生成的数据仓库包裹父级组件,再从子组件中获取数据仓库中的数据
说明:ContextApi在管理登录用户数据这类具有公共属性的数据是一把利器,但使用起来会相当繁琐
constContextWrapper=React.createContext();//注意这里的 是指我们App的根组件,在包裹根组件后我们可以在任意子页面组件中取值
任意
{context=> 会渲染成{context.name}{context.job} }MegaGalaxyFrontEndEngineer
缺点:理解需要花一些功夫,写法繁琐,且只适合特定类型的数据,要明确组件间的包裹关系
Global传值
推荐指数:♥♥♥
适用范围:页面间传值
兼容性:IOS/Android
原理:利用Node.js中的顶级对象Global来挂载属性,利用属性传值
说明:在跳转的页面前,可以把需要传递的参数挂载在Global对象上,在跳转后即可在Global对象上取过相同的键取到对应的值,例如:在A页面跳转B页面时,Global.params={name:'Jalon',id:'123456'},在跳转之后,即可通过Global.params拿到值,除了普通的字值串,布尔值,对象,数组,也可以传递函数,但要注意带有this.setState方法的函数传递后调用可能会报错.
缺点:如果挂载的属性/方法过多易造成冲突与污染,不利于维护
个人建议:在react-navigation跳转传值与DeviceEventEmitter维护不方便的情况下才使用,但尽量少用,以免造成Global属性的污染与冲突
总结了5种常见的参数/数据传递的方法,以个人角度来看,推荐顺序为ReactNavigation导航传值>DeviceEventEmitter触发事件并传值>AsyncStorageKey-Value式的存储传参,最后两种是在特殊场景下才会去使用,所以朋友们,在合适的场景选择合适的方式去传值,会为ReactNative项目的开发带来更为理想的效果,感谢您的阅读,也希望大家多多支持毛票票。