天天看點

React Native 指定頁面實體傳回監聽

React Native 指定頁面實體傳回監聽

在Android機上,實體傳回是一個很常用的功能,本文将講解如何在react-native中對實體傳回進行處理,分别為首頁面連續兩次退出程式,普通頁面回到上一頁,指定頁面特殊處理。

一. 首頁面連續兩次退出程式及普通頁面傳回上一頁

  1. 首先我們要先在頁面上增加實體監聽,建議在主Navigator頁面增加,就是有如下空間的頁面裡。
<Navigator
                style={styles.navigator}
                configureScene={this.configureScene}
                renderScene={this.renderScene}
                initialRoute={{
                    id: 'Splash',
                }} />
           
  1. 添加監聽
componentWillMount() {
        if (Platform.OS === 'android') {
            BackAndroid.addEventListener('hardwareBackPress', this.handleBackButton);
        }
    }
    handleBackButton() {
        for (let i = this.handlers.length - ; i >= ; i--) {
            if (this.handlers[i]()) {
                return true;
            }
        }//指定頁面特殊處理
        const routers = this.navigator.getCurrentRoutes();
        if (routers.length > ) {
            this.navigator.pop();
            return true;
        }
        let now = new Date().getTime();
        if (now - lastClickTime < ) {
        //2.5秒内點選後退鍵兩次推出應用程式
            return false;//控制權交給原生
        }
        lastClickTime = now;
        ToastAndroid.show('再按一次退出一個',ToastAndroid.SHORT);
        return true;
    }
           

對了 這裡的this.handleBackButton要在頁面初始化的地方bind一下

this.handleBackButton = this.handleBackButton.bind(this);
           
  1. 基本完成

    經過上面的處理,我們可以基本的實作對實體傳回的監聽,如果不是初始頁面(即routes裡還有其他頁面),則把頁面彈出,回到上一頁,否則在2,5秒内按兩次實體傳回就可以退出程式。

二. 特殊頁面的傳回監聽

1. childContextTypes
通過添加 childContextTypes 和 getChildContext() 到 context 的提    供者,React 自動向下傳遞資料然後在元件樹中的任意元件(也就是說任意子元件,在本次中将是一個函數 )都能通過定義 contextTypes 通路 context 中的資料
           

大概是這麼個意思,建議要弄明白的可以自己查一下

2. 首頁面處理
在初始化(constructor(props) )的地方建立一個數組,将用來存儲那些特定頁面的監聽函數
           
3. 目前頁面新增兩個函數
用來添加及删除特殊頁面的實體監聽,并将它們提供給向下的元件樹
           
addBackButtonListener(listener) {
        this.handlers.push(listener);
    }
    removeBackButtonListener(listener) {
        this.handlers = this.handlers.filter((handler) => handler !== listener);
    }

    static childContextTypes = {
        addBackButtonListener: React.PropTypes.func,
        removeBackButtonListener: React.PropTypes.func
      }
    getChildContext() {
        return {
            addBackButtonListener: this.addBackButtonListener,
            removeBackButtonListener: this.removeBackButtonListener,
        };
    }
           
4. 子元件(特殊頁面)特殊處理

(1) 擷取父元件的函數

static contextTypes = {
    removeBackButtonListener: React.PropTypes.func.isRequired,
    addBackButtonListener: React.PropTypes.func.isRequired,
  };
           

(2) 新增新的監聽函數

handleBackButton() {
        let {navigator} = this.props;
        let routers = navigator.getCurrentRoutes();
        if (routers[routers.length - ].id === "XXXXXXXX") {
            //為了保險起見 因為有時候監聽不會立刻被解除安裝,防止在其他頁面觸發該監聽
            this.existAlert();//特殊處理
            return true;
        } else {
            return false;
        }
    }
           

(3) 将函數添加到監聽隊列中(仍要記得bind)

componentDidMount() {  
    this.context.addBackButtonListener(this.handleBackButton);              
}
componentWillUnmount() {
    this.context.removeBackButtonListener(this.handleBackButton);        
}
           

(4)功能完成了。

三.實作的原理

通過childContextTypes,首頁面将增删實體監聽的函數提供給了子頁面。在子頁面中,如果需要特殊處理實體傳回監聽,可以調用該方法,把目前頁面的特殊處理方法添加到首頁面的監聽隊列中。當按下實體傳回,會先檢視特殊監聽隊列,是否有特殊處理,有的話特殊處理,沒有的話,将按普通的實體傳回進行處理
           

代碼

下面是我的github上的源碼,裡面特殊處理的頁面為滑出的抽屜

還有一些練手小東西,有興趣的可以看一下

源碼