React Native自定義路由管理

1,自定義路由

衆所周知,無論是在原生Android仍是iOS,它們都有一個默認的路由路由棧管理類。因爲React Native官方沒有提供路由管理的組件,因此咱們須要使用react-navigation插件提供的Stack.Navigator組件來管理路由。react

Stack.Navigator使用的命名路由,所謂命名路由,指的是路由須要先聲明而後才能使用。爲了方便管理路由頁面,咱們會將路由放到一個統一的位置,好比screens包下,以下所示。
在這裏插入圖片描述npm

而後,咱們在項目的screens/index.js文件中新建一個常量,主要用來管理聲明的路由,以下所示。函數

export const stacks = [
  {
    name: 'AllMovieScreen',
    component: AllMovieScreen,
    options: {headerShown: false},
  },
  {
    name: 'CitySelectScreen',
    component: CitySelectScreen,
    options: {title: '選擇城市'},
  },
  …. //省略其餘路由頁面
];

而後,咱們再新建一個MainStackScreen.js文件,用來實現路由的跳轉、返回等操做。同時,MainStackScreen類的另外一個做用是統一導航欄的樣式,代碼以下所示。工具

onst MainStack = createStackNavigator();

function MainStackScreen({navigation}) {
  return (
    <MainStack.Navigator
      initialRouteName="App"
      screenOptions={{
        headerTitleAlign: 'center',
        headerStyle: {
          shadowOffset: {width: 0, height: 0},
          shadowColor: '#E5E5E5',
          backgroundColor: '#fff',
        },
        gestureEnabled: true,
        headerBackTitleVisible: false,
        headerLeft: () => (
          <TouchableOpacity
            onPress={() => navigation.goBack()}
            style={{padding: 10, paddingRight: 30}}>
            <Icon name="chevron-thin-left" size={20} color="#222222" />
          </TouchableOpacity>),
      }}>
      <MainStack.Screen
        name="App"
        component={BottomTab}
        options={{headerShown: false}}/>
      {stacks.map((item, index) => (
        <MainStack.Screen
          key={index.toString()}
          name={item.name}
          component={item.component}
          options={item.options}/>
      ))}
    </MainStack.Navigator>
  );
}

export default MainStackScreen;

在上面的代碼,咱們建立了一個creens/index.js文件來申明應用的路由,而後在MainStackScreen 類中使用map循環完成路由的註冊。能夠看到,通過上面的處理後,路由管理是很是清晰的,當有新的頁面時只須要往creens/index.js文件中添加路由便可。spa

2,Tab導航

在React Native應用開發中,react-navigation除了提供路由管理功能外,還支持Tab導航和Drawer導航。而且,在最新的版本中,Tab導航、Drawer導航和Stack導航所依賴的庫是分開的,因此在開發過程當中須要單獨安裝。插件

對於Tab導航來講,須要在項目中安裝Tab導航須要的bottom-tabs庫,命令以下。code

npm install @react-navigation/bottom-tabs

建立Tab導航時須要用到createBottomTabNavigator()方法,它須要提供導航器和路由兩個屬性,分別對應Tab.Navigator和Tab.Screen兩個組件,最後還須要使用NavigationContainer組件包裹它們,以下所示。component

import {createBottomTabNavigator} from '@react-navigation/bottom-tabs';
import {NavigationContainer} from '@react-navigation/native';

const BottomTabs = createBottomTabNavigator();

export default function BottomTabScreen() {
  return (
    <NavigationContainer>
      <BottomTabs.Navigator
        initialRouteName="Home"
        screenOptions={({route}) => ({
          tabBarIcon: ({focused}) => {
            return (
              <Image source={ focused? tabImage[`${route.name}_active`]
                    : tabImage[route.name]
                }
                style={{width: 26, height: 26}}/>
            ); }})}
        tabBarOptions={{
          activeTintColor: 'tomato',
          inactiveTintColor: 'gray',
          style: {
            backgroundColor: '#fff',
          },
        }}>
        <BottomTabs.Screen
          name="Home"
          component={HomeScreen}
          options={{
            tabBarLabel: '電影',
          }}/>
         
…. //省略其餘代碼

        <BottomTabs.Screen
          name="Mine"
          component={MineScreen}
          options={{
            tabBarLabel: '個人',
          }}/>
      </BottomTabs.Navigator>
    </NavigationContainer>
  );
}

同時,bottom-tabs插件還提供了不少其餘有用的組件和屬性,開發者能夠根據須要進行選擇。運行上面的代碼,效果下圖所示。
在這裏插入圖片描述圖片

3,數據回傳

有時候,咱們有這樣一種需求:跳轉到下一個頁面,並在下一個頁面選擇了數據後進行回傳。好比:
在這裏插入圖片描述ci

在上面的場景中,咱們須要對活動列表進行篩選,那麼在跳轉到活動篩選頁面後,須要回傳選中的活動類型,對於這種場景,咱們須要對react-navigation進行怎樣的處理呢?

首先,咱們在screens/index.js文件中註冊活動類型頁面,以下所示。

{
  name: 'SelectorScreen',
  component: SelectorScreen,
  options: nav => {
    const {route} = nav;
    const {params = {}} = route;
    const {title = '活動類型', onRightPress = () => {}} = params;
    return {
       title,
       headerRight: () => (
         <TouchableOpacity
            onPress={onRightPress}
            style={styles.button}>
            <Text style={{color: '#fff', fontSize: 14}}>肯定</Text>
         </TouchableOpacity>
        ),
      };
    },
  }

同時,活動篩選頁面的數據是由活動列表頁面傳遞過來的。因此在使用的時候,只須要使用上文封裝好的路由工具執行跳轉操做便可,代碼以下。

navigate('SelectorScreen', {
      values: categories.map(c => c.andGroupName),
      defaultValues: categoryName,
      onConfirm: changeCategory,
    });

能夠看到,爲了獲取篩選頁面選擇的數據,咱們在跳轉的時候定義了一個onConfirm回調函數。接着,咱們在新建的活動篩選頁面接收上一個頁面傳遞過來的活動數據並使用列表展現出來便可,以下所示。

function SelectorScreen({navigation, route}) {
  const {values = [], defaultValues = [], onConfirm} =route.params || {};
  const [selected, setSelected] = useState(defaultValues);

  const _onRightPress = () => {
    onConfirm(selected);
    navigation.goBack();
  };

  useEffect(() => {
    navigation.setParams({onRightPress: _onRightPress});
  }, [selected]);

  const onPressItem = val => {
    let arr = [];
arr = [val];  
setSelected(arr);
  };

  const renderItem = ({item}) => {
    const renderRight = () => {
    const isSelected = selected.includes(item);
    return (
      <ListItem
        text={item}
        renderRight={renderRight}
        onPress={() => onPressItem(item)} />
    );
  };

  return (
    <View style={styles.bg}>
      <FlatList
        keyExtractor={(item, index) => item + index}
        data={values}
        renderItem={renderItem}
        ListFooterComponent={<View height={120} />} />
    </View>
  );
};

const styles = StyleSheet.create({
 …. //省略樣式代碼
});

export default SelectorScreen;

選擇完活動類型以後,如何將選擇的結果返回給上一個頁面呢。此時就用到了前文定義的onConfirm回調函數,以下所示。

const {values = [], defaultValues = [], onConfirm} =route.params || {};

const _onRightPress = () => {
    onConfirm(selected);        //onConfirm回調函數回傳數據
    navigation.goBack();
 };
相關文章
相關標籤/搜索