浅谈React Native 传参的几种方式(小结)


Posted in Javascript onMay 21, 2019

在React Native 中由于业务的需要, 我们往往要在诸多的页面间,组件之间做一些参数的传递与管理, 在这里我总结了几大经过验证,稳定好用的方式给大家

React Navigation 导航传值

推荐指数: ♥ ♥ ♥ ♥ ♥

适用范围: 相互跳转的页面间传值

兼容性: IOS/Android

原理: React Navigation 为页面的 props 上挂载了 navigation 对象, 可用来做路由跳转,在做页面跳转时可以携带参数/回调方法前往目标页面, 从而达到传参的目的

说明: 这是官方推荐,也是我们在业务开发中用得最多,最为推崇的一种传参方式, 思想与 web 在 querystring 上带参跳转类似,只是实现方式略微不同, 举例

导航传值即可正向传值,也可反向传值 例如 A->B 是正向传值, 而B->A 则是反向传值

正向传值:

A页面跳转向B页面, 在组件内通过访问 this.props.navigation.navigate('B', { 

type: 'list',   
 callback:data => { console.log('data in callback: ', 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页面后

'data in callback: ', { id: '123', message: 'list really?'});

 也即callBack 中的 data 参数就是 { id: '123', message: 'list really?'}

DeviceEventEmitter 触发事件并传值

推荐指数: ♥ ♥ ♥ ♥

适用范围: 页面间传值/组件间传值

兼容性: IOS/Android

原理: 利用 React Native 包中提供的 DeviceEventEmitter 模块订阅事件,触发事件,并能同时传值

说明: DeviceEventEmitter 从名字就能知道他是基于事件订阅的机制来进行传值的, 当订阅某种事件后, 触发的时候会调用订阅事件的回调, 并能把值传送过去, 并且在同页面内的组间件, 不同页面间都可以传值, 但前提是页面还未被销毁(销毁后事件的订阅会取消), 例如:

DeviceEventEmitter.addListener('warning_event', (data) => { console.log('data: ', data);})
 DeviceEventEmitter.emit('warning_event', { name: 'Mega Galaxy'});
 // data: { name: 'Mega Galaxy' }

在emit(触发)事件后, 回调函数的入参就变成了我们所传递的 { name: 'Mega Galaxy'}, 

也可不传值,不传值时 callback 的入参就是 undefined

缺点: 本质是对自定义事件的监听与触发, 当页面逻辑复杂时,代码会相对变大, 维护成本变高, 且监听过多会造成性能问题, 还有一点就是在页面销毁时必须移除监听: 如果忘记移除监听会怎么样? 那emit 一次的时候, 会多响应一次你加上去的监听

componentDidMount() {
 this.eventHandler = DeviceEventEmitter.addListner('event_name', callback);
}
componentWillUnmount() {
 this.eventHandler.remove();
}

个人建议: 在梳理清楚页面逻辑后,合理使用

AsyncStorage Key-Value 式的存储传参

推荐指数: ♥ ♥ ♥ ♥

适用范围: 跨页面 跨组件的任性传参

兼容性: IOS/Android

原理: 利用类似 web 中 localStorage 的思想,将参数/数据存放在 AsyncStorage中,在需要的地方再取出来

说明: localStorage 在 web 中的实用性 与 受欢迎程度大家是知道的, AsyncStorage其实就是 rn 版的 localStorage, 略微不同的是它是异步的,只返回 Promise, 所以与 async/await 结合会非常好用

···

在A页面

saveOrderData = async () => {
 try {
 const orderData = [{ id: 1, data: []}, { id: 2, data: []}]
 await AsyncStorage.setItem('Order_data_cache', JSON.stringify(orderData ));
 } catch (error) {
 // Error saving data
 }
}

在B页面

loadOrderData = async () => {
 const __orderData = await AsyncStorage.getItem('Order_data_cache');
 const orderData = JSON.parse(__orderData);
 this.setState({ orderData });
}

缺点: 以 Key-Value 式的存储传参,可能重点还是在数据存储上, 且因为涉及到 I/O 的操作,在部份低端机型上,有卡顿的可能性

React Context Api 传参(新版Context Api)

推荐指数: ♥ ♥ ♥

适用范围: 不同页面间的组件共享公共类的数据

兼容性: IOS/Android

原理: 利用生成的数据仓库包裹父级组件, 再从子组件中获取数据仓库中的数据

说明: Context Api 在管理登录用户数据这类具有公共属性的数据是一把利器, 但使用起来会相当繁琐

const ContextWrapper = React.createContext();
 <ContextWrapper.Provider value={{ name: 'Mega Galaxy', job: 'FrontEnd Engineer' }}
 <App />
 <ContextWrapper.Provider>
 // 注意这里的 <App /> 是指我们 App的根组件,在包裹根组件后 我们可以在任意子页面组件 中取值

任意 <App /> 里的子页面组件中

<ContextWrapper.Counsumer> 
 { context => <Text> { context.name } { context.job }</Text> }
 </ContextWrapper.Counsumer>
 会渲染成 <Text> Mega Galaxy FrontEnd Engineer </Text>

缺点: 理解需要花一些功夫, 写法繁琐,且只适合特定类型的数据,要明确组件间的包裹关系

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种常见的参数/数据传递的方法,以个人角度来看, 推荐顺序为 React Navigation 导航传值 > DeviceEventEmitter 触发事件并传值 > AsyncStorage Key-Value 式的存储传参, 最后 两种是在特殊场景下才会去使用,所以朋友们,在合适的场景选择合适的方式去传值,会为React Native项目的开发带来更为理想的效果,感谢您的阅读,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
基于Jquery制作的幻灯片图集效果打包下载
Feb 12 Javascript
Javascript中的String对象详谈
Mar 03 Javascript
JS获取URL中参数值(QueryString)的4种方法分享
Apr 12 Javascript
jquery插件bxslider用法实例分析
Apr 16 Javascript
JS DOM实现鼠标滑动图片效果
Sep 17 Javascript
jQuery学习之DOM节点的插入方法总结
Jan 22 Javascript
vue实现消息的无缝滚动效果的示例代码
Dec 05 Javascript
微信小程序实现action-sheet弹出底部菜单功能【附源码下载】
Dec 09 Javascript
vscode中vue-cli项目es-lint的配置方法
Jul 30 Javascript
简单的React SSR服务器渲染实现
Dec 11 Javascript
vue 插槽简介及使用示例
Nov 19 Vue.js
element中Steps步骤条和Tabs标签页关联的解决
Dec 08 Javascript
JavaScript函数式编程(Functional Programming)声明式与命令式实例分析
May 21 #Javascript
JS判断数组里是否有重复元素的方法小结
May 21 #Javascript
JS计算两个数组的交集、差集、并集、补集(多种实现方式)
May 21 #Javascript
vue路由守卫+登录态管理实例分析
May 21 #Javascript
vue实现跨域的方法分析
May 21 #Javascript
vue动态绑定class的几种常用方式小结
May 21 #Javascript
express启用https使用小记
May 21 #Javascript
You might like
PHP自带方法验证邮箱是否存在
2016/02/01 PHP
php自动载入类用法实例分析
2016/06/24 PHP
宝塔面板在NGINX环境中TP5.1如何运行?
2021/03/09 PHP
JS写的数字拼图小游戏代码[学习参考]
2008/10/29 Javascript
清空上传控件input file的值
2010/07/03 Javascript
关于JS字符串函数String.replace()
2013/04/07 Javascript
jQuery()方法的第二个参数详解
2015/04/29 Javascript
iscroll.js的上拉下拉刷新时无法回弹的解决方法
2016/02/18 Javascript
Javascript字符串拼接小技巧(推荐)
2016/06/02 Javascript
Bootstrap学习笔记之css样式设计(1)
2016/06/07 Javascript
详解AngularJs ui-router 路由的简单介绍
2017/04/26 Javascript
Express使用html模板的详细代码
2017/09/18 Javascript
vue路由跳转时判断用户是否登录功能的实现
2017/10/26 Javascript
vue项目前端微信JSAPI与外部H5支付相关实现过程及常见问题
2020/04/14 Javascript
[05:35]DOTA2英雄梦之声_第13期_拉比克
2014/06/21 DOTA
[38:40]2018DOTA2亚洲邀请赛 4.6淘汰赛 mineski vs LGD 第一场
2018/04/10 DOTA
Python中用memcached来减少数据库查询次数的教程
2015/04/07 Python
Python的Flask站点中集成xhEditor文本编辑器的教程
2016/06/13 Python
Python开发SQLite3数据库相关操作详解【连接,查询,插入,更新,删除,关闭等】
2017/07/27 Python
Python数据可视化教程之Matplotlib实现各种图表实例
2019/01/13 Python
Python os.access()用法实例
2019/02/18 Python
python实现抽奖小程序
2020/04/15 Python
详解基于python-django框架的支付宝支付案例
2019/09/23 Python
详解使用python3.7配置开发钉钉群自定义机器人(2020年新版攻略)
2020/04/01 Python
PyTorch: Softmax多分类实战操作
2020/07/07 Python
selenium框架中driver.close()和driver.quit()关闭浏览器
2020/12/08 Python
美国韩国化妆品和护肤品购物网站:Beautytap
2018/07/29 全球购物
Skyscanner新西兰:全球领先的旅游搜索网站
2019/08/26 全球购物
Nike瑞士官网:Nike CH
2021/01/18 全球购物
业务代表的岗位职责
2013/11/16 职场文书
酒店办公室文员岗位职责
2013/12/18 职场文书
小学语文教研活动总结
2014/07/01 职场文书
教师四风对照检查材料思想汇报
2014/09/17 职场文书
幼儿园教师师德表现自我评价
2015/03/05 职场文书
JS的深浅复制详细
2021/10/16 Javascript
Go 内联优化让程序员爱不释手
2022/06/21 Golang