浅谈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 相关文章推荐
JavaScript 异步调用框架 (Part 3 - 代码实现)
Aug 04 Javascript
event.srcElement 用法笔记e.target
Dec 18 Javascript
js调试系列 断点与动态调试[基础篇]
Jun 18 Javascript
JavaScript常用小技巧小结
Dec 29 Javascript
javascript设计简单的秒表计时器
Sep 05 Javascript
使用jquery获取url以及jquery获取url参数的实现方法
May 25 Javascript
微信开发 使用picker封装省市区三级联动模板
Oct 28 Javascript
Vue添加请求拦截器及vue-resource 拦截器使用
Nov 23 Javascript
Vue在页面右上角实现可悬浮/隐藏的系统菜单
May 04 Javascript
vue中使用elementUI组件手动上传图片功能
Dec 13 Javascript
ES6使用 Array.includes 处理多重条件用法实例分析
Mar 02 Javascript
eslint+prettier统一代码风格的实现方法
Jul 22 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 JSON格式数据交互实例代码详解
2011/01/13 PHP
PHP提示Cannot modify header information - headers already sent by解决方法
2014/09/22 PHP
54个提高PHP程序运行效率的方法
2015/07/19 PHP
PHP数据库编程之MySQL优化策略概述
2017/08/16 PHP
Avengerls vs Newbee BO3 第二场2.18
2021/03/10 DOTA
总结AJAX相关JS代码片段和浏览器模型
2007/08/15 Javascript
javascript Array.prototype.slice使用说明
2010/10/11 Javascript
JS+css 图片自动缩放自适应大小
2013/08/08 Javascript
Javascript执行效率全面总结
2013/11/04 Javascript
如何判断元素是否为HTMLElement元素
2013/12/06 Javascript
js或jquery实现页面打印可局部打印
2014/03/27 Javascript
js实现飞入星星特效代码
2014/10/17 Javascript
jQuery+ajax中getJSON() 用法实例
2014/12/22 Javascript
深入浅析同源策略和跨域访问
2015/11/26 Javascript
js+html5实现的自由落体运动效果代码
2016/01/28 Javascript
详解微信小程序入门五: wxml文件引用、模版、生命周期
2017/01/20 Javascript
thinkphp标签实现bootsrtap轮播carousel实例代码
2017/02/19 Javascript
详述 Sublime Text 打开 GBK 格式中文乱码的解决方法
2017/10/26 Javascript
js canvas实现红包照片效果
2018/08/21 Javascript
Element UI框架中巧用树选择器的实现
2018/12/12 Javascript
8个有意思的JavaScript面试题
2019/07/30 Javascript
JavaScript基础之this和箭头函数详析
2019/09/05 Javascript
原生jQuery实现只显示年份下拉框
2020/12/24 jQuery
[01:51]2014DOTA2国际邀请赛 这个赛场没有失败者VGTi5再见
2014/07/23 DOTA
解决python2.7 查询mysql时出现中文乱码
2016/10/09 Python
Python 描述符(Descriptor)入门
2016/11/20 Python
python之Character string(实例讲解)
2017/09/25 Python
对python3 sort sorted 函数的应用详解
2019/06/27 Python
python Django 创建应用过程图示详解
2019/07/29 Python
解决Python对齐文本字符串问题
2019/08/28 Python
PyCharm MySQL可视化Database配置过程图解
2020/06/09 Python
Aeropostale官网:美国著名校园品牌及青少年服饰品牌
2019/03/21 全球购物
Timberland俄罗斯官方网上商店:全球领先的户外品牌
2020/03/15 全球购物
个人三严三实对照检查材料思想汇报
2014/09/22 职场文书
经营目标责任书
2015/05/08 职场文书
Redis基本数据类型Set常用操作命令
2022/06/01 Redis