设为首页收藏本站

react native【免费】VIP视频教程 rn开发者交流论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 2528|回复: 167

[课堂笔记] 38、手把手教React Native实战之物理back键详解

  [复制链接]

401

主题

762

帖子

6969

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
6969
发表于 2016-6-18 16:06:25 | 显示全部楼层 |阅读模式
#38、手把手教React Native实战之物理back键详解

在上一节课代码的基础上:

分析路由栈的结构(帖子后面有图片),见该集视频教程   栈:先进后出,后进先去!

  1. componentWillMount() {
  2.     if (Platform.OS === 'android') {
  3.       BackAndroid.addEventListener('hardwareBackPress', this.onBackAndroid);
  4.     }
  5.   }
  6.   componentWillUnmount() {
  7.     if (Platform.OS === 'android') {
  8.       BackAndroid.removeEventListener('hardwareBackPress', this.onBackAndroid);
  9.     }
  10.   }

  11. onBackAndroid = () => {
  12.         const { navigator } = this.props;
  13.         const routers = navigator.getCurrentRoutes();
  14.         console.log('当前路由长度:'+routers.length);
  15.         if (routers.length > 1) {
  16.             navigator.pop();
  17.             return true;//接管默认行为
  18.         }
  19.         return false;//默认行为

  20.     };
复制代码


需要注意的是,不论是bind还是箭头函数,
每次被执行都返回的是一个新的函数引用,
因此如果你还需要函数的引用去做一些别的事情(譬如卸载监听器),那么你必须自己保存这个引用


// 错误的做法
  1. class PauseMenu extends React.Component{
  2.     componentWillMount(){
  3.         AppStateIOS.addEventListener('change', this.onAppPaused.bind(this));
  4.     }
  5.     componentDidUnmount(){
  6.         AppStateIOS.removeEventListener('change', this.onAppPaused.bind(this));
  7.     }
  8.     onAppPaused(event){
  9.     }
  10. }
复制代码


// 正确的做法1
  1. class PauseMenu extends React.Component{
  2.     constructor(props){
  3.         super(props);
  4.         this._onAppPaused = this.onAppPaused.bind(this);
  5.     }
  6.     componentWillMount(){
  7.         AppStateIOS.addEventListener('change', this._onAppPaused);
  8.     }
  9.     componentDidUnmount(){
  10.         AppStateIOS.removeEventListener('change', this._onAppPaused);
  11.     }
  12.     onAppPaused(event){
  13.     }
  14. }
复制代码



// 正确的做法2
  1. class PauseMenu extends React.Component{
  2.     componentWillMount(){
  3.         AppStateIOS.addEventListener('change', this.onAppPaused);
  4.     }
  5.     componentDidUnmount(){
  6.         AppStateIOS.removeEventListener('change', this.onAppPaused);
  7.     }
  8.     onAppPaused = (event) => {
  9.         //把方法直接作为一个arrow function的属性来定义,初始化的时候就绑定好了this指针
  10.     }
  11. }
复制代码


特别说明【回复本帖可见】
游客,如果您要查看本帖隐藏内容请回复



例子:“再按一次退出应用”
  1. //到了主页了
  2.       if (this.lastBackPressed && this.lastBackPressed + 2000 >= Date.now()) {
  3.         //最近2秒内按过back键,可以退出应用。
  4.         return false;
  5.       }
  6.       this.lastBackPressed = Date.now();
  7.       ToastAndroid.show('再按一次退出应用',ToastAndroid.SHORT);
  8.       return true;
复制代码


我们在监听函数中不能决定是否要调用默认行为,要等待一个异步操作之后才调用默认行为,此时可以通过第二种办法:

使用BackAndroid.exitApp()来退出应用。

例子:在退出应用之前保存数据

写法1:
  
  1. onBackAndroid = () =>{
  2.     saveData().then(()=>{
  3.       BackAndroid.exitApp();
  4.     });
  5.     return true;
  6.   }
复制代码

   
  在监听函数中,我们开始异步事件,并直接return true。此时默认行为不会被调用。当保存完毕后,我们调用exitApp(),触发默认行为,退出应用。
  
  写法2:
   
  1. onBackAndroid = async () =>{
  2.     await saveData();
  3.     BackAndroid.exitApp();
  4.   }
复制代码

   
  这里我们用了async函数,async 函数总是返回一个Promise,Promise作为一个对象,也被认为是一个“真值”,所以这种情况下默认行为总是不会被调用。当保存完毕后,我们调用exitApp(),触发默认行为,退出应用。
  
例子:根据当前界面决定作何动作
  有时候我们有这样的需求:当用户处于某些界面下时,back键要做特殊的动作,如:提示用户是否要保存数据,或者解锁界面禁止back键返回等等。此时,最佳实践是在route或route中对应的Component上保存关于如何处理back键的信息:
   
  1. onBackAndroid = () => {
  2.     const nav = this.navigator;
  3.     const routers = nav.getCurrentRoutes();
  4.     if (routers.length > 1) {
  5.       const top = routers[routers.length - 1];
  6.       if (top.ignoreBack || top.component.ignoreBack){
  7.         // 路由或组件上决定这个界面忽略back键
  8.         return true;
  9.       }
  10.       const handleBack = top.handleBack || top.component.handleBack;
  11.       if (handleBack) {
  12.         // 路由或组件上决定这个界面自行处理back键
  13.         return handleBack();
  14.       }
  15.       // 默认行为: 退出当前界面。
  16.       nav.pop();
  17.       return true;
  18.     }
  19.     return false;
  20.   };
复制代码







路由栈信息.png
react native vip论坛免费发布【手把手教react native实战开发】视频教程,立志于打造全互联网最全面最详细最易懂的React Native
开发视频教程,Facebook已经在多项产品中使用了React Native,并且将持续地投入建设,让我们引领react native开发的潮流!
回复

使用道具 举报

0

主题

274

帖子

644

积分

RN高级VIP

Rank: 9Rank: 9Rank: 9

积分
644
发表于 2016-6-19 21:39:22 | 显示全部楼层
学习学习
回复

使用道具 举报

9

主题

264

帖子

775

积分

RN高级VIP

Rank: 9Rank: 9Rank: 9

积分
775
发表于 2016-6-20 00:14:41 | 显示全部楼层
持续学习中
回复 支持 反对

使用道具 举报

0

主题

13

帖子

36

积分

新手上路

Rank: 1

积分
36
发表于 2016-6-21 07:16:29 | 显示全部楼层
手教React Native实战之物理back键详解
回复 支持 反对

使用道具 举报

12

主题

304

帖子

922

积分

RN高级VIP

Rank: 9Rank: 9Rank: 9

积分
922
发表于 2016-6-21 08:16:28 | 显示全部楼层
大赞
回复

使用道具 举报

0

主题

9

帖子

20

积分

新手上路

Rank: 1

积分
20
发表于 2016-6-21 14:19:06 | 显示全部楼层
kkkkkkkkkvrrv
回复 支持 反对

使用道具 举报

0

主题

5

帖子

16

积分

新手上路

Rank: 1

积分
16
发表于 2016-6-21 14:59:07 | 显示全部楼层
昨天看了下,今天实践
回复 支持 反对

使用道具 举报

0

主题

8

帖子

24

积分

新手上路

Rank: 1

积分
24
发表于 2016-6-22 23:08:16 | 显示全部楼层
很好,很好,很好
回复 支持 反对

使用道具 举报

1

主题

106

帖子

327

积分

RN高级VIP

Rank: 9Rank: 9Rank: 9

积分
327
发表于 2016-6-24 16:10:25 | 显示全部楼层
hah hah hah hah hah hah
回复 支持 反对

使用道具 举报

1

主题

27

帖子

119

积分

RN高级VIP

Rank: 9Rank: 9Rank: 9

积分
119
发表于 2016-6-25 18:42:46 | 显示全部楼层
再按一次退出应用
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|ReactNative Inc.    

GMT+8, 2018-11-17 17:20 , Processed in 0.170075 second(s), 29 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表