用React Navigation實現RN組件間的跳轉

    傳統的單頁面應用,基於url的hash值進行路由跳轉,hybrid App的跳轉原理與此不同,其原理更像是web瀏覽器的前進後退。

    在 web 瀏覽器中,使用<a>標籤作爲錨點,鏈接到不同的頁面。 當用戶單擊某個鏈接時, 該 URL 就會被推送到瀏覽器歷史記錄堆棧。 瀏覽器通過兩個棧實現前進後退。一個棧X,一個棧Y。每次跳轉到新頁面時將此頁面壓入X,並清空Y;當點擊後退按鈕式時,將X出棧,並壓入到Y;當點擊前進按鈕時,將Y出棧,壓入X。X爲空時表示沒有頁面可以後退瀏覽了,當Y爲空時表示沒有頁面可以前進瀏覽了。

    React Navigation是RN官方提供的工具,它有三種導航方式:

    Stack navigation:頂部導航條,用來跳轉頁面和傳遞參數

    Tab navigation:底部標籤欄,用來區分模塊

    Drawer navigation:抽屜,從App左側滑出一個頁面

    stack navigation類似瀏覽器的導航處理,本文我們討論的就是stack navigation方式。 當用戶與它進行交互時,應用程序會從導航堆棧中新增和刪除頁面,這樣就實現了不同頁面的切換。

    下面是我學習過程對官方文檔的一個個人總結。

    官方文檔:React Navigation

插件安裝

    npm install react-navigation --save
    npm install react-native-gesture-handler

    最簡單的實現一般包括以下幾個步驟

1、定義路由

    使用createStackNavigator方法,該方法返回 React 組件。

import {createStackNavigator} from 'react-navigation';
import Main from '../Main';
import Page1 from '../Page1';
import Page2 from '../Page2';

export const Router = createStackNavigator({
    Main: {screen: Main}, // routeName: {screen: component}
    Page1: {screen: Page1},
    Page2: {screen: Page2},
  }
);

    你可以將此文件直接寫在App.js中,或者單獨寫一個文件,再在App.js中引用。我這裏單獨寫成一個文件。

    注意需要用AppContainer包裹整個環境。

    App.js

import React, { Component } from 'react';
import { createAppContainer } from "react-navigation";
import {Router} from './src/navigator/Router';

const AppContainer = createAppContainer(Router);
export default class App extends Component {
  render() {
    return <AppContainer />;
  }
}

2、實現跳轉

    定義好路由之後,調用this.props.navigation.navigate('Page1')方法實現跳轉。

    這裏還有另一個方法this.props.navigation.push('Page1'),它與navigate()方法的區別是,如果從當前頁跳轉到當前頁(比如我們複用組件,只是改變裏面的某些參數),調用 navigate(),它不會做任何改變,push()方法則不考慮現有導航,直接添加路由,所以可以實現當前頁到當前頁的跳轉。

    返回上一頁,用this.props.navigation.goBack()方法。

3、數據傳遞

    this.props.navigation.navigate('RouteName', yourParam)

    讀取數據:this.props.navigation.state.params。讀取數據還可以用this.props.navigation.getParam('itemId', 'defaultValue'),這種方式,因爲我們已經設置了一個default value,所以不必處理參數爲空的情況。

    修改當前頁的參數:this.props.navigation.setParam ({otherParam: 'Updated!'})

4、配置標題欄

單個組件標題欄

    通過配置navigationOptions實現自定義標題欄。

class HomeScreen extends React.Component {
  static navigationOptions = {
    title: 'Home',
    headerStyle: {
      backgroundColor: '#f4511e',
    },
    headerTintColor: '#fff',
    headerTitleStyle: {
      fontWeight: 'bold',
    },
  };

  /* render function, etc */
}

設置通用標題欄樣式

    上述方法是在單個頁面中設置標題欄的方法,如果我們要爲所有頁面的header設置統一的樣式,無需在每個頁面中寫重複的代碼,在createStackNavigator配置defaultNavigationOptions即可。

export const Router = createStackNavigator({
    Main: {screen: Main}, // routeName: {screen: component}
    Page1: {screen: Page1},
    Page2: {screen: Page2},
  },
  {
    initialRouteName: 'Main', // 初始化加載的頁面
    defaultNavigationOptions: { // 設置統一的header樣式
      headerStyle: {
        backgroundColor: '#f4511e',
      },
      headerTintColor: '#fff',
      headerTitleStyle: {
        fontWeight: 'bold',
      },
    },
  }
);

標題欄傳值

    注意navigation的引用方式

class DetailsScreen extends React.Component {
  static navigationOptions = ({ navigation }) => {
    return {
      title: navigation.getParam('otherParam', 'A Nested Details Screen'),
    };
  };

  /* render function, etc */
}

使用自定義組件替換標題欄

class LogoTitle extends React.Component {
  render() {
    return (
      <Image
        source={require('./spiro.png')}
        style={{ width: 30, height: 30 }}
      />
    );
  }
}

class HomeScreen extends React.Component {
  static navigationOptions = {
    // headerTitle instead of title
    headerTitle: <LogoTitle />,
  };
  /* render function, etc */
}

5、爲標題欄添加按鈕

  static navigationOptions = {
    headerTitle: <LogoTitle />,
    headerRight: (
      <Button
        onPress={() => alert('This is a button!')}
        title="Info"
        color="#fff"
      />
    ),
  };

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章