React Native 传参的几种方式

更新日期: 2019-05-21阅读: 3.4k标签: native

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项目的开发带来更为理想的效果,感谢您的阅读!


链接: https://fly63.com/article/detial/3392

来聊聊怎么写react-native上的样式吧

在react-native上是怎么写样式的吧,和传统的web不一样的是,在react-native上面是没有css代码,不过得益于Yoga,我们可以在客户端上像写css一样的去书写我们的样式。

WKWebView 里 JS 和 native 通信的例子

初始化 wkwebview,设置 message handler,native 端注册了 testecho 的messageHandler,实现 WKScriptMessageHandler协议,执行JS 代码 ,所以 JS 可以通过 window.webkit.messageHandlers.testecho.postMessage 来回调客户端,和文档中说的一样

由使用request-promise-native想到的异步处理方法

因为js语言的特性,使用node开发程序的时候经常会遇到异步处理的问题。对于之前专长App开发的我来说,会纠结node中实现客户端API请求的“最佳实践”。下面以OAuth2.0为场景,需要处理的流程:获取access token、使用获取到的token,发起API请求、处理API数据

React Native项目使用react-apollo实现更新缓存的两种方式

GraphQL是一个API查询语言,他可以将使用PostgreSQL写的server代码自动生成Query或者Mutation,非常的方便。而Apollo Client就是一个强大的JavaScript GraphQL客户端。对于cache,在Apollo Client中有着强大的管理策略。

11个React Native组件库

React Native 是 Facebook 2015年开源的 Javascript 框架,旨在使用 Javascript 高效开发手机端 App。根据大众的需求,我们列出了一个有用的React-Native UI库列表,可以帮助你更好地入门React Native。

如何正确选型,React Native 还是 Native?

随着 H5 标准的发布以及推广,使得移动应用的开发也受到了很大影响,出于效率、成本等原因,移动应用的开发不再完全依赖于 “原生”。近日越发火热的混合应用(Hybrid App)介于 Web 应用和原生应用之间

react-native报错Cannot get property packageName on null object

react-native打包安卓apk的时候,报错Cannot get property packageName on null object,完全没有头绪,研究了半天才发现竟然是因为package.json里面scripts自定了命令导致的,无法理解为何会影响安卓打包并且报错packageName null

React Native 添加 Redux 支持

之前写的项目都是人家编写好的脚手架,里面包含项目所需的环境文件,但由于有些东西用不到打包增加软件体积,所以自己从头搭建个环境。是基于 Native Base + react-navigation + Redux 的 React Native 脚手架,现在项目环境如下

Flutter platform view 使用篇

Flutter作为备受关注的跨平台的开发框架,长远来看,前景肯定是比较好的,在其基础组件还未完善与成熟之前,能够高效的复用现有的native组件,是比较合适的方案。官方提供了Plugin的方式,允许将一个成熟的native组件(比如mapview)

JSBridge 初探

近些年,移动端普及化越来越高,开发过程中选用 Native 还是 H5 一直是热门话题。Native 和 H5 都有着各自的优缺点,为了满足业务的需要,公司实际项目的开发过程中往往会融合两者进行 Hybrid 开发。Native 和 H5 分处两地,看起来无法联系,那么如何才能让双方协同实现功能呢?

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!