iT邦幫忙

2023 iThome 鐵人賽

DAY 16
0

當頁面很多時,可進一步透過巢狀路由來管理頁面,讓頁面架構更清楚。以 Google Podcast 為例,下面有一個 Bottom Navigation 。其中媒體庫的頁面中有四個連結「訂閱」、「待播清單」、「下載內容」、「紀錄」,點擊訂閱後則會進到訂閱頁。
https://ithelp.ithome.com.tw/upload/images/20230918/20129635q5wX50dVkb.png
https://ithelp.ithome.com.tw/upload/images/20230918/20129635ndh8hsLDdT.png

稍加拆解會發現下方 Bottom Navigation 算一個 Navigator ,包含三個 Screen 「首頁」、「探索」、「媒體庫」。而媒體庫本身也算一個 Navigator ,包含四個 Screen 「訂閱」、「待播清單」、「下載內容」、「紀錄」。這就是所謂的巢狀路由。
https://ithelp.ithome.com.tw/upload/images/20230918/20129635iG5AnjL9mv.png

現在讓我們嘗試撰寫一個巢狀路由架構。為了簡化複雜度,讓我們直接利用前面已經做好的 SettingsScreen 改寫,使他底下多出帳號管理 AccountScreen 和語言設定 LanguageScreen 。
https://ithelp.ithome.com.tw/upload/images/20230918/20129635sBUmU8tEYE.png

創建 AccountScreen 和 LanguageScreen 。

function AccountScreen() {
  return (
    <View>
      <Text>帳號管理</Text>
    </View>
  );
}
function LanguageScreen() {
  return (
    <View>
      <Text>語言設定</Text>
    </View>
  );
}

接著改寫 SettingsScreen ,基本架構就像前面講過的 Stack Navigation ,只是為了方便判別他是個 Stack ,將元件名稱更改成 SettingsStack。 BottomNavigation 引入的元件,也別忘了一併更改名稱:

import {createNativeStackNavigator} from '@react-navigation/native-stack';

const Stack = createNativeStackNavigator();

function SettingsStack() {
  return (
    <Stack.Navigator>
      <Stack.Screen name="AccountScreen" component={AccountScreen} />
      <Stack.Screen name="LanguageScreen" component={LanguageScreen} />
    </Stack.Navigator>
  );
}

完成後, AccountScreen 和 LanguageScreen 就會被掛在 SettingStack 的路由之下。
https://ithelp.ithome.com.tw/upload/images/20230918/20129635t9K7SckcKB.png

為了讓進入 SettingStack 時,可以有一個菜單頁能進 AccountScreen 和 LanguageScreen ,可以再製作一個 SettingsMenuScreen 元件:

function SettingsMenuScreen({navigation}) {
  return (
    <View>
      <TouchableOpacity onPress={() => navigation.navigate('AccountScreen')}>
        <Text>帳號管理</Text>
      </TouchableOpacity>
      <TouchableOpacity onPress={() => navigation.navigate('LanguageScreen')}>
        <Text>語言設定</Text>
      </TouchableOpacity>
    </View>
  );
}

再引入 SettingStack 中:

function SettingStack() {
  return (
    <Stack.Navigator>
      <Stack.Screen name="SettingsMenuScreen" component={SettingsMenuScreen} />
      <Stack.Screen name="AccountScreen" component={AccountScreen} />
      <Stack.Screen name="LanguageScreen" component={LanguageScreen} />
    </Stack.Navigator>
  );
}

https://ithelp.ithome.com.tw/upload/images/20230918/20129635UdDiZ1krrL.png

最後,運用前面提過的 options 屬性,我們能把 Settings 這個 Header 隱藏。

function BottomeNavigation() {
  return (
    <Tab.Navigator>
      <Tab.Screen name="Home" component={HomeScreen} />
      <Tab.Screen
        name="Settings"
        component={SettingsStack}
        options={{
          headerShown: false,
          headerTransparent: true,
          headerBackground: () => null,
        }}
      />
    </Tab.Navigator>
  );
}

https://ithelp.ithome.com.tw/upload/images/20230918/20129635JxGKhPqala.png
https://ithelp.ithome.com.tw/upload/images/20230918/20129635OVxCm9eo8C.png

運用上面所做的,來看一下巢狀路由有哪些特性:

  1. 每個 Navigator 都有自己的路由紀錄。
  2. 每個 Navigator 能獨立設定 Options ,例如 Header 的 title 。
    https://ithelp.ithome.com.tw/upload/images/20230918/20129635G20nGIUorS.png
  3. 每個 Navigator 的參數都是獨立的,無法在父或子 Navigator 取得。
  4. 在巢狀路由的子元件回上一頁時,會回到父路由元件的 Stack Navigation 。舉例來說,當我們從 HomeScreen 進入 AccountScreen ,再從 AccountScreen 回上頁,會回到 SettingsMenuScreen 。
  5. 父路由元件的 Header 會壓在子路由 Header 上面。
    https://ithelp.ithome.com.tw/upload/images/20230918/20129635gZOUKXfsel.png

最後補充一個特殊情況:要如何從一個 Stack ,進到另一個 Stack 中的巢狀路由下的子路由呢?
https://ithelp.ithome.com.tw/upload/images/20230918/20129635rJMY4tkwQZ.png

為了模擬出問題,我們建立一個 HomeStack ,並將他和 SettingsStack 一起掛在 BottomNavigation 底下:

function HomeStack() {
  return (
    <Stack.Navigator>
      <Stack.Screen name="HomeScreen" component={HomeScreen} />
    </Stack.Navigator>
  );
}
function BottomeNavigation() {
  return (
    <Tab.Navigator>
      <Tab.Screen name="Home" component={HomeStack} />
      <Tab.Screen
        name="Settings"
        component={SettingsStack}
        options={{
          headerShown: false,
          headerTransparent: true,
          headerBackground: () => null,
        }}
      />
    </Tab.Navigator>
  );
}

現在 HomeScreen 和 AccountScreen 分別被掛在 HomeStack 與 SettingsStack 之下。要從 HomeScreen 跳到 AccountScreen ,需要在第一個參數提供 Stack name ,在第二個參數附上有真正 Screen 名稱的物件。

function HomeScreen({navigation}) {
  return (
    <View>
      <Text>Home</Text>
      <TouchableOpacity
        onPress={() =>
          navigation.navigate('Settings', {screen: 'AccountScreen'})
        }>
        <Text>帳號管理</Text>
      </TouchableOpacity>
    </View>
  );
}

上一篇
Day 15. 以 React Navigation 做路由設定與建立 Bottom Navigation
下一篇
Day 17. 在 React Native 中引入 Icon
系列文
即使明天老闆突然叫你用 React Native 也可以跟他說好沒問題30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言