1. 程式人生 > >React Native之React Navigation導航器

React Native之React Navigation導航器

最近在學習React Native,關於介面跳轉這一塊,文件上面寫的並不清晰,自己也是研究了很久才搞清楚用法,這裡記錄下。

譯註:從0.44版本開始,Navigator被從react native的核心元件庫中剝離到了一個名為react-native-deprecated-custom-components的單獨模組中。如果你需要繼續使用Navigator,則需要先npm i facebookarchive/react-native-custom-components安裝,然後從這個模組中import,即import { Navigator } from ‘react-native-deprecated-custom-components’.

今後社群主推的導航控制元件是react-navigation。

如果我們安裝了yarn,那麼只要使用yarn add react-navigation命令安裝這個庫就可以使用了。

如果我們在index.js入口中這麼寫的話

import { AppRegistry } from 'react-native';
import App from './App';
AppRegistry.registerComponent('ReactNativeSimple', () => App);

那麼我們想在App元件中跳轉到別的頁面,那麼我們就可以把navigation申明在App檔案中然後匯出,這裡需要注意,default關鍵字不能申明在App類中了要申明在navigation匯出的時候。
ps:navigation必須default申明原因我猜測因為default匯出的類,在適用import匯入的時候可以隨便改寫名字例如上面如果App是用default申明匯出的那麼上面程式碼import App from ‘./App’;我們可以隨便寫成import xxx from ‘./App’; 都可以,如果不適用default申明的話那麼import 匯入時候必須跟類名一模一樣。 我們匯出的navigation變數名叫啥系統也不知道,所以只能用default申明瞭。

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 * @flow
 */

import React, { Component } from "react";
import {
  Platform,
  StyleSheet,
  Text,
  View,
  FlatList,
  Image,
  TouchableOpacity,
  TouchableHighlight,
  NativeModules,
  Alert
} from "react-native";
import DemoComponent from "./DemoComponent"
; const instructions = Platform.select({ ios: "Press Cmd+R to reload,\n" + "Cmd+D or shake for dev menu", android: "Double tap R on your keyboard to reload,\n" + "Shake or press menu button for dev menu" }); import { StackNavigator } from "react-navigation"; export class App extends Component<Props> { static defaultProps = { textValue: "首頁預設文字" }; constructor(props) { super(props); this.state = { textValue: this.props.textValue }; } testOnpress = () => { this.props.navigation.navigate("Profile", { name: "Jane" }); }; render() { return ( <View style={styles.container}> <FlatList data={[{ key: "wubo" }]} renderItem={({ item }) => ( <View style={styles.listItem}> <Image style={{ width: 30, height: 30 }} source={require("./icon.jpg")} /> <Text onPress={this.testOnpress}>{this.state.textValue}</Text> </View> )} /> </View> ); } } const Navigate= StackNavigator({ App: { screen: App }, Profile: { screen: DemoComponent } }); const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: "#F5FCFF" }, listItem: { flexDirection: "row", justifyContent: "center" }, welcome: { fontSize: 20, textAlign: "center", margin: 10 }, instructions: { textAlign: "center", color: "#333333", marginBottom: 5 } }); export default AppN1;

我們在Navigation路由中申明瞭元件頁面後,這個元件就具有了navigation props屬性,我們就可以跳轉到路由中申明的其他頁面了。

但如果我們這樣寫的話主要有幾點問題。 1. 我們的App沒有用default申明,所以其他地方匯出使用時必須是App類名不能更改這點上面已經提到。 2 . 如果我們把每個介面要跳轉的頁面都申明在這個元件類中,那麼缺乏統一的管理顯得非常混亂,這是不允許的。
所以上面方法雖然可以實現跳轉但是強烈不建議這麼做。

常規方式我們可以單獨建立個js類單獨管理所有要跳轉的頁面。
例如我建立個NavigationManager.js檔案

import { StackNavigator } from "react-navigation";

import DemoComponent from "./DemoComponent";
import App from "./App";

const Navigate = StackNavigator(
  {
    App: { screen: App ,
      navigationOptions: {
        header: null
      }
    },
    Profile: { screen: DemoComponent }
  },
  {
    initialRouteName: "App"
  }
);

export default Navigate;

這裡預設顯示的頁面是App元件
我們可以把所有需要跳轉的頁面都放在這個js申明的navigation中,然後預設匯出,記住navigation一定要預設匯出。

然後App元件程式碼我們修改成這樣

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 * @flow
 */

import React, { Component } from "react";
import {
  Platform,
  StyleSheet,
  Text,
  View,
  FlatList,
  Image,
  TouchableOpacity,
  TouchableHighlight,
  NativeModules,
  Alert
} from "react-native";
const instructions = Platform.select({
  ios: "Press Cmd+R to reload,\n" + "Cmd+D or shake for dev menu",
  android:
    "Double tap R on your keyboard to reload,\n" +
    "Shake or press menu button for dev menu"
});
export default class App extends Component<Props> {
  static defaultProps = {
    textValue: "首頁預設文字"
  };
  constructor(props) {
    super(props);
    this.state = {
      textValue: this.props.textValue
    };
  }
  testOnpress = () => {
    this.props.navigation.navigate("Profile", { name: "Jane" });
  };
  render() {
    return (
      <View style={styles.container}>
        <FlatList
          data={[{ key: "wubo" }]}
          renderItem={({ item }) => (
            <View style={styles.listItem}>
              <Image
                style={{ width: 30, height: 30 }}
                source={require("./icon.jpg")}
              />
              <Text onPress={this.testOnpress}>{this.state.textValue}</Text>
            </View>
          )}
        />
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#F5FCFF"
  },
  listItem: {
    flexDirection: "row",
    justifyContent: "center"
  },
  welcome: {
    fontSize: 20,
    textAlign: "center",
    margin: 10
  },
  instructions: {
    textAlign: "center",
    color: "#333333",
    marginBottom: 5
  }
});

我們在index.js中把入口從App改成Navigate.

import { AppRegistry } from 'react-native';
import Navigate from './NavigationManager';
AppRegistry.registerComponent('ReactNativeSimple', () => Navigate);

此時跟我們之前是一樣的效果,但是把所有要跳轉的頁面管理在一起,程式碼就清爽很多,後期利於維護。