天天看點

React Navigation 入門(四) - 螢幕導航 Navigation 屬性詳解

RN 版本:0.50

操作環境:Windows 10

React Navigation 版本:1.0.0-beta.20

文章同步自簡書:http://www.jianshu.com/p/6d178490b164

之前已經說過,每個在 navigator 中注冊過的頁面都會接受一個 navigation 屬性,它包含以下幾屬性:

  • navigate

    - (helper) 連接配接其他頁面
  • state

    - 頁面目前的狀态/路由
  • setParams

    - (helper) 更新路由的參數
  • goBack

    - (helper) 關閉目前活動頁面并傳回
  • dispatch

    - 給路由器發送指令行為

在之前的幾篇文章中,我們已經接觸過

navigate

(用來跳轉頁面)、

state

(用來擷取傳遞的參數)和

setParams

(用來改變參數),這篇文章将會對它們進行更詳細的說明。

注意:

navigation

屬性被傳遞給了每一個導航相關元件并且包括導航器。不過需要注意的不同點是導航器 navigator 的

navigation

屬性不會包含那些 helper 類的函數(

navigate

,

goBack

等),它隻有

state

dispatch

屬性。如果你想要使用導航器

navigation

屬性中的

navigate

函數,你必須使用

dispatch

來傳遞一個導航操作意圖(關于 Navigation Actions 下一篇文章會講)。

與 Redux 內建時的注意事項

注:這段文字直接翻譯自官方文檔,由于我還沒有了解過 redux,是以看得不是太懂。有興趣的可以看看 原文。

由于許多人對 navigator 頂級 API 的了解錯誤,他們并不能很好地正确使用 navigation 屬性與 redux 的關聯。導航器 navigator 如果沒有接收到 navigation 屬性話它會保持自己的狀态,但這個并不是你通常情況下關聯 redux 時想要的特征。對于嵌套在主導航器裡面的各個導航器,你總是會想把 navigation 屬性傳遞下去。這就允許你的頂級導航器去傳達并給子導航器提供狀态。這個時候你隻需要将頂級路由與 redux 內建,因為其他的路由都被包含在了它的裡面。

navigate - 連結其他螢幕

在 app 中跳轉其它頁面時調用的方法。它有如下參數:

navigate(routeName, params, action)

  • routeName

    - 在你的 app 中已經注冊過的打算跳轉的目的路由名稱
  • params

    - 傳給目的路由的參數
  • action

    - (進階)如果螢幕是導航器,則在子路由中運作的操作。有關支援的操作的完整清單,請參閱 操作文檔,暫時打算下一篇文章再介紹。
class HomeScreen extends React.Component {
  render() {
    const {navigate} = this.props.navigation;
    return (
      <View>
        <Text>This is the home screen of the app</Text>
        <Button
          // 跳轉到 Profile 頁面并傳遞參數 name
          onPress={() => navigate('Profile', {name: 'Brent'})}
          title="Go to Brent's profile"
        />
      </View>
     )
   }
}
           

state - 螢幕目前狀态/路由

一個螢幕可以通過

this.props.navigation.state

擷取它的路由,它傳回的是一個如下類型的對象:

{
  // the name of the route config in the router
  // 路由器中設定的路由名稱
  routeName: 'Profile',
  // a unique identifier used to sort routes
  // 為友善管理路由而産生的唯一辨別
  key: 'main0',
  // an optional object of string options for this screen
  // 給目前螢幕可供選擇的參數對象
  params: { hello: 'world' }
}
           
class ProfileScreen extends React.Component {
  render() {
    const {state} = this.props.navigation;
    // state.routeName === 'Profile'
    return (
      // 擷取參數 name,我們之前已經見到過這種用法了
      <Text>Name: {state.params.name}</Text>
    );
  }
}
           

setParams - 改變路由參數

觸發

setParams

方法允許頁面改變路由中的參數,這對于更新頭部标題及按鈕很有用處。上一篇文章中我們曾經介紹過這個方法。

class ProfileScreen extends React.Component {
  render() {
    const {setParams} = this.props.navigation;
    return (
      <Button
        onPress={() => setParams({name: 'Lucy'})}
        title="Set title name to 'Lucy'"
      />
     )
   }
}
           

goBack - 關閉目前活動頁面并傳回

給該方法提供一個 key,來決定要從哪個路由傳回(即要關閉哪個頁面)。預設情況下,會關閉掉調用該方法的目前路由。如果目标是想要回到 anywhere 而不具體地說明要關閉哪個頁面,可以調用

goBack(null)

class HomeScreen extends React.Component {
  render() {
    const {goBack} = this.props.navigation;
    return (
      <View>
        <Button
          // 關閉目前的 HomeScreen
          onPress={() => goBack()}
          title="Go back from this HomeScreen"
        />
        <Button
          // 這裡測試的結果也是關閉了目前的 HomeScreen
          onPress={() => goBack(null)}
          title="Go back anywhere"
        />
        <Button
          // 關閉從 'screen-123' 到棧頂的所有路由
          onPress={() => goBack('screen-123')}
          title="Go back from screen-123"
        />
      </View>
     )
   }
}
           

從指定的頁面傳回

假設我們有四個路由 A B C D 依次入棧:

navigation.navigate(SCREEN_KEY_A);
...
navigation.navigate(SCREEN_KEY_B);
...
navigation.navigate(SCREEN_KEY_C);
...
navigation.navigate(SCREEN_KEY_D);
           

假如你在 screen D 并且想要傳回到 screen A(關閉 D, C 和 B),那麼你就需要這麼寫:

// will go to screen A FROM screen B
navigation.goBack(SCREEN_KEY_B) 
           

注意:這個方法裡面的 key 值,并不是定義 navigator 時我們給頁面自定義的 key,而是上面 state 裡面的

state.key

。并且我們在 D 中不能直接通過

this.props.navigation.state.key

來擷取,因為它擷取的是 D 的 key,是以我們要在 B 中擷取到它,然後一級一級的傳遞給 D,最後調用

navigation.goBack(SCREEN_KEY_B)

來回到 A。

React Navigation 入門(四) - 螢幕導航 Navigation 屬性詳解

dispatch - 給路由發送一個行為

使用 dispatch 給路由指派任意的 navigation 行為,其它的 navigation 函數使用背景的 dispatch 來實作。記住如果你想指派 react-navigation 行為的話,你應該使用庫裡提供的 action creators。檢視 Navigation Actions 來擷取完整的可指派行為(具體行為會在下一篇文章進行說明)。

import { NavigationActions } from 'react-navigation'

const navigateAction = NavigationActions.navigate({
  routeName: 'Profile',
  params: {},

  // navigate can have a nested navigate action that will be run inside the child router
  // navigate 可以嵌套 navigate action,它會在子路由裡面執行
  action: NavigationActions.navigate({ routeName: 'SubProfileRoute'})
})
this.props.navigation.dispatch(navigateAction)