1. 程式人生 > 其它 >基礎篇章:關於 React Native 之 Navigator 元件的講解

基礎篇章:關於 React Native 之 Navigator 元件的講解

(友情提示:RN學習,從最基礎的開始,大家不要嫌棄太基礎,會的同學請自行略過,希望不要耽誤已經會的同學的寶貴時間)

今天我們來講講Navigator這個小傢伙,呃……不能說小傢伙,因為它還是很厲害的,有了它我就就能實現各個介面的跳轉和切換。所以它的名字叫導航器。來,今天我們就一起來學習學習它。

使用我Navigator可以讓你們實現在應用內不同頁面的切換,我是用JavaScript實現的,而且我有兩個:IOS和Android,如果在IOS上使用請用我的雙胞胎兄弟NavigatorIOS,因為它充分利用本地的UIKit導航。

要想設定Navigator,使用我,你們必須確定一個或多個呼叫routes物件,去定義每個場景。你們還可以利用renderScene方法,導航欄可以根據指定的路由來渲染場景。

官網基礎小例子

render() {
  const routes = [
    {title: 'First Scene', index: 0},
    {title: 'Second Scene', index: 1},
  ];
  return (
    <Navigator
      initialRoute={routes[0]}
      initialRouteStack={routes}
      renderScene={(route, navigator) =>
        <TouchableHighlight onPress={() => {
          if (route.index === 0) {
            navigator.push(routes[1]);
          } else {
            navigator.pop();
          }
        }}>
        <Text>Hello {route.title}!</Text>
        </TouchableHighlight>
      }
      style={{padding: 100}}
    />
  );
}

nitialRoute 在上面的示例中,initialRoute 用於指定的第一個路由。它包含一個標題屬性,標識路由。RenderScene 屬性返回一個函式,顯示路由標題文字。 initialRouteStack initialRoute指定第一個顯示的頁面,而要設定多個場景,你們通過initialRouteStack屬性了。通過上面例子,我們可以看到定義了兩個路由,而且每個路由都有一個用於管理被渲染場景的索引屬性。在renderScene方法中有一個觸控事件,觸控決定導航器是推或者彈出哪個導航場景。

我們可以在Navigator上設定標題導航欄Navigation Bar,在標題導航欄中我們可以通過routeMapper屬性去設定左,右和標題導航欄。在配置左,右,和標題導航欄專案,您可以訪問資訊,如當前路由物件和導航狀態。這使您可以為每個場景自定義標題以及按鈕。例如,您可以選擇隱藏場景中的左鍵。 例子如下:

<Navigator
  renderScene={(route, navigator) =>
    // ...
  }
  navigationBar={
     <Navigator.NavigationBar
       routeMapper={{
         LeftButton: (route, navigator, index, navState) =>
          { return (<Text>Cancel</Text>); },
         RightButton: (route, navigator, index, navState) =>
           { return (<Text>Done</Text>); },
         Title: (route, navigator, index, navState) =>
           { return (<Text>Awesome Nav Bar</Text>); },
       }}
       style={{backgroundColor: 'gray'}}
     />
  }
/>

場景轉換

要想改變場景的動畫和轉換,相當於我們Android中的進場和轉場動畫,我們可以通過configureScene屬性來獲得對於給定路線的配置物件。如下:

<Navigator
  renderScene={(route, navigator) =>
    // ...
  }
  configureScene={(route, routeStack) =>
    Navigator.SceneConfigs.FloatFromBottom}
/>

屬性

  • configureScene function 就是通過它配置場景轉換的。它有如下屬性:
    • Navigator.SceneConfigs.PushFromRight (default)
    • Navigator.SceneConfigs.FloatFromRight
    • Navigator.SceneConfigs.FloatFromLeft
    • Navigator.SceneConfigs.FloatFromBottom
    • Navigator.SceneConfigs.FloatFromBottomAndroid
    • Navigator.SceneConfigs.FadeAndroid
    • Navigator.SceneConfigs.HorizontalSwipeJump
    • Navigator.SceneConfigs.HorizontalSwipeJumpFromRight
    • Navigator.SceneConfigs.VerticalUpSwipeJump
    • Navigator.SceneConfigs.VerticalDownSwipeJump
  • initialRoute object 定義啟動時載入的路由。路由是導航欄用來識別渲染場景的一個物件。initialRoute必須是initialRouteStack中的一個路由。initialRoute預設為initialRouteStack中最後一項。
  • initialRouteStack [object] 存放路由的一個數組
  • navigationBar node 上面介紹了
  • navigator object
  • onDidFocus function 每當導航切換完成或初始化之後,呼叫此回撥,引數為新場景的路由
  • onWillFocus function 會在導航切換之前呼叫,引數為目標路由
  • renderScene function 用來渲染每一個路由指定的頁面
  • sceneStyle 樣式風格

方法

  • immediatelyResetRouteStack(nextRouteStack) 用新的路由陣列來重置路由棧
  • jumpTo(route) 跳轉到傳入的已有的場景並且不解除安裝
  • jumpForward(0) 跳轉到下一個場景
  • jumpBack(0) 同上相反的意思
  • push(route) 跳轉到新的場景,並且將場景入棧,你可以稍後用jump forward 跳轉回去
  • popN(n) 回到ñ場景一次。當N = 1,行為相匹配pop()方法。當N是無效的(負或大於當前的路線計算),什麼也不做。
  • pop(0) 跳轉回去並且解除安裝掉當前場景
  • replaceAtIndex(route, index, cb) 替換掉指定序列的路由場景
  • replace(route) 用一個新路由替換當前場景
  • replacePrevious(route) 替換掉之前的場景
  • popToTop(0) pop到棧中的第一個場景,解除安裝掉所有的其他場景
  • popToRoute(route) pop到路由指定的場景,在整個路由棧中,處於指定場景之後的場景將會被解除安裝
  • replacePreviousAndPop(route) 取代之前的場景,並彈出它
  • resetTo(route) 跳轉到指定的新場景,並重置路由棧
  • getCurrentRoutes() 獲取當前棧裡的路由

例項

效果圖

怎麼樣?我的樣子很帥吧,是不是很想和我玩,那就趕緊行動起來吧,我已經迫不及待的想跟你們一起玩了。來看看怎麼和我玩的例項程式碼吧。

程式碼

import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  Navigator,
  Image,
  TouchableHighlight,
  TouchableOpacity,
  View
} from 'react-native';

NavigationBarRouteMapper = {
   LeftButton(route, navigator, index, navState) {
     if (route.id === 'first') {
       return null;
     }
     previousRoute = navState.routeStack[index - 1];
     return (
       <TouchableOpacity
         onPress={() => navigator.pop()}
         style={styles.navBarLeftButton}>
         <Image source={require('./back.png')} style={styles.backImage}>
         </Image>
       </TouchableOpacity>
     );
   },
   RightButton(route, navigator, index, navState) {
     if (route.id === 'second') {
       return null;
     }
     return (
       <TouchableOpacity
         onPress={() => navigator.push({id:'second',title:'第二頁',data:"我是從第一頁跳轉過來的"})}
         style={styles.navBarRightButton}>
         <Text style={[styles.navBarButtonText]}>
           下一頁
         </Text>
       </TouchableOpacity>
     );
   },

   Title(route, navigator, index, navState) {
     return (
       <Text style={[styles.navBarTitleText]}>
         {route.title}
       </Text>
     );
   },
 };

export default class NavigatorDemo extends Component {
   render(){
      return (
        <Navigator
          style = {styles.container}
          initialRoute={{id:"first",title:"第一頁"}}
          renderScene={this.renderNav}
          configureScene={(route, routeStack) => Navigator.SceneConfigs.HorizontalSwipeJump}
          navigationBar={
            <Navigator.NavigationBar
              routeMapper={NavigationBarRouteMapper}
              style={{backgroundColor:'white'}}
           />
          }
          />
      );
    }

    renderNav(route,nav){
        switch (route.id) {
          case 'first':
            return <FirstScreen navigator={nav} title="第一頁"/ >;
          case 'second':
            return (<SecondScreen navigator={nav} title="第二頁" data={route.data}/>);
        }
    }
}

class FirstScreen extends Component{
   toSecond=()=>{
     this.props.navigator.push({id:"second",title:"第二頁",data:"我是第二頁"});
  }
   render(){
     return (
       <View style={styles.firstView}>
         <TouchableHighlight
          style={{padding:10}}
          onPress={this.toSecond}
          underlayColor="blue">
            <Text style={styles.contentText}>第一頁</Text>
         </TouchableHighlight>
       </View>
     );
   }
 }

class SecondScreen extends Component{
   toFirst=()=>{
     this.props.navigator.pop();
   }
   render(){
     return (
       <View style={styles.secondView}>
         <TouchableHighlight
          style={{padding:10}}
          onPress={this.toFirst}
          underlayColor="red">
            <Text style={styles.contentText}>{this.props.data}</Text>
         </TouchableHighlight>
       </View>
     );
   }
 }

const styles = StyleSheet.create({
   backImage:{
     width:15,
     height:30,
   },
  navBarTitleText: {
    color: 'black',
    fontWeight: '500',
    marginTop:20,
  },
  navBarLeftButton: {
    paddingLeft: 10,
    paddingTop:15,
  },
  navBarRightButton: {
    paddingRight: 10,
    paddingTop:20,
  },
  navBarButtonText: {
    color: '#5890FF',
  },
   container: {
     flex: 1,
   },
   firstView:{
     flex: 1,
     backgroundColor:'red',
     justifyContent: 'center',
   },
   secondView:{
     flex:1,
     justifyContent: 'center',
     backgroundColor:'blue',
   },
   contentText:{
     fontSize:22,
     color:'white',
     textAlign:'center',
   },
});

AppRegistry.registerComponent('NavigatorDemo', () => NavigatorDemo);