4. 路由

创建时间:2024-10-29 11:57
长度:9088
浏览:0
评论:0

expo

   我mac 用的是expo来做环境变量的,expo有自己的router

   链接

   

   expo路由是一个约定式的路径,放在app目录下的文件及文件夹都是路由

   _layout.jsx 它定义共享的 UI 元素,例如标题和标签栏,以便它们在不同的路由之间保持一致


   屏幕之间切换

import { Link } from 'expo-router';
....
<Link href="/Page1">page1 </Link>

   

   设置标题栏

       注意:android是不支持返回标题的设置的,这些长度内容都有限制

import React from 'react';
import { View, Text, Button } from 'react-native'
import { Stack, useLocalSearchParams, router } from 'expo-router';
import { TextInput } from 'react-native';


export default function Page1() {
  const params = useLocalSearchParams<{ [key: string]: string}>();

  return <View style={{ flex: 1, backgroundColor: '#eee', paddingTop: 30 }}>
    <Stack.Screen
      options={{
        title: 'My home',
        headerStyle: { backgroundColor: 'green' },
        headerTintColor: '#fff',
        headerTitleStyle: {
          fontWeight: 'bold',
        },
        headerBackTitle: '返回',
        headerRight() {
          return <Button 
            title={params?.mode === 'edit' ? '保存' : '编辑'}  
            onPress={() => {
              router.setParams({ mode: params?.mode === 'edit' ? 'save' : 'edit'})
            }}
          />
        }
      }}
    />
    <Text>欢迎来到Page1</Text>
    <TextInput 
      editable={params?.mode === 'edit'}
      style={{
        borderColor: '#ccc',
        borderWidth: 1,
        height: 50,
      }}
    />
  </View>
}

       



   隐藏标题栏

import { useNavigation } from 'expo-router';

...
const navigation = useNavigation();

useEffect(() => {
    navigation.setOptions({ headerShown: false });
}, [navigation]);


   底部导航

       在expo中,要创建底部导航,在app/(tabs)目录下创建,然后在_layout.jsx中导入就可以


import { Tabs } from 'expo-router';
import React from 'react';

import { TabBarIcon } from '@/components/navigation/TabBarIcon';
import { Colors } from '@/constants/Colors';
import { useColorScheme } from '@/hooks/useColorScheme';

export default function TabLayout() {
  const colorScheme = useColorScheme();

  return (
    <Tabs
      screenOptions={{
        tabBarActiveTintColor: Colors[colorScheme ?? 'light'].tint,
        // headerShown: false, // 隐藏顶部导航
      }}>
      <Tabs.Screen
        name="index"
        options={{
          title: 'Home',
          tabBarIcon: ({ color, focused }) => (
            <TabBarIcon name={focused ? 'home' : 'home-outline'} color={color} />
          ),
        }}
      />
      <Tabs.Screen
        name="explore"
        options={{
          title: 'Explore',
          tabBarIcon: ({ color, focused }) => (
            <TabBarIcon name={focused ? 'code-slash' : 'code-slash-outline'} color={color} />
          ),
        }}
      />
      <Tabs.Screen
        name="Page1"
        options={{
          tabBarActiveTintColor: '#f00',
          tabBarLabel: (params) => {
            return <Text style={{ color: params.color}} >Page1</Text>
          },
          tabBarIcon: ({ color, focused }) => (
            <TabBarIcon name={focused ? 'code-slash' : 'code-slash-outline'} color={color} />
          ),
        }}
      />
    </Tabs>
  );
}

   

       tabBarLabel 可以用来设置字体颜色等    


   顶部导航

       在标题栏下方还可以加一个导航,官方文档

       还有一个库更加灵活:react-native-pager-view, 这个库比上面的库增加了动画

       


安装
npm install @react-navigation/material-top-tabs react-native-tab-view
npm install react-native-pager-view
# Mac iOS
npx pod-install ios

使用
import { createMaterialTopTabNavigator } from '@react-navigation/material-top-tabs';

const Tab = createMaterialTopTabNavigator();

function MyTabs() {
  return (
    <Tab.Navigator>
      <Tab.Screen name="Home" component={HomeScreen} />
      <Tab.Screen name="Settings" component={SettingsScreen} />
    </Tab.Navigator>
  );
}    


   替换屏幕

       就是跳转到新屏幕内容后,无法返回

import { router } from 'expo-router';

...
<Text onPress={() => router.replace('/Page1')}>page1 </Text>
...

       

   抽屉导航器

       安装依赖

       npx expo install @react-navigation/drawer react-native-gesture-handler react-native-reanimated

       

       在app/_layout.jsx

import { GestureHandlerRootView } from 'react-native-gesture-handler';
import { Drawer } from 'expo-router/drawer';

  return (
    <GestureHandlerRootView style={{ flex: 3 }}>

    {/* <ThemeProvider value={colorScheme === 'dark' ? DarkTheme : DefaultTheme}>
      <Stack>
        <Stack.Screen name="(tabs)" options={{ headerShown: false }} />
        <Stack.Screen name="+not-found" />
      </Stack>
    </ThemeProvider> */}

        <Drawer>
          <Drawer.Screen
            name="Page1" // This is the name of the page and must match the url from root
            options={{
              drawerLabel: 'Page1',
              title: 'overview',
            }}
          />
        </Drawer>
      </GestureHandlerRootView>
  );

   



传统的react native 屏幕跳转

   这里都是抄其它地方来的,自行验证

    # 安装路由库
    npm i --save react-navigation

然后创建方式去官网看一下吧,每个版本都不太一样的

   在react-navigation中有常用的导航器有以下7种:

      • createStackNavigator:类似于普通的Navigator,屏幕上方导航栏;
      • create TabNavigator: create TabNavigator已弃用,使用createBottomTabNavigator和/或createMaterialTopTabNavigator替代;
      • createBottom TabNavigator:相当于iOS里面的TabBarController,屏幕下方的标签栏;
      • createMaterialTopTabNavigator:屏幕顶部的材料设计主题标签栏;
      • createDrawerNavigator:抽屉效果,侧边滑出;
      • createSwitchNavigator:SwitchNavigator 的用途是一次只显示一个页面。

       你可以通过以上7种导航器来创建你APP,可以是其中一个也可以多个组合,这个可以根据具体的应用场景并结合每一个导航器的特性进行选择。

       • Screen navigation prop(屏幕导航属性):通过navigation可以完成屏幕之间的调度操作,例如打开另一个屏幕;

       • screen navigationdptions(屏幕导航选项):通过navigationOptions可以定制导航器显示屏幕的方式(例如:头部标题,选项卡标签等);


   导航器所支持的Props

const SomeNav = createStackNavigator/createBottomTabNavigator/createMaterialTopTabNaviga
// config
}) ;
const AppNav = createAppContainer (SomeNav) ;

<AppNav
    screenProps={xxx}
    ref={nav = { navigation = nav; }}
    onNavigationStateChange=(prevState, newState, action)=>{
    }
/>
      • ref:可以通过 ref 属性获取到 navigation;
      • onNavigationStateChange(prevState, newState, action):顶级节点除了 ref 属性之外,还接受 onNavigationStateChange(prevstate,newState,action) 属性,每次当导航器所管理的 state 发生改变时,都会回调该方法;
        • prevState:变化之前的state;
        • newState: 新的state;
        • 导致state变化的action;
        • screenProps:向子屏幕传递额外的数据,子屏幕可以通过this.props.screenProps获取到该数据。

       

       Screen Navigation Prop(屏幕的navigation Prop)

           当导航器中的屏幕被打开时,它会收到一个 navigation prop,navigation prop是整个导航环节的关键一员,接下来就详细讲解一下 navigation 的作用。


      this.props.navigation包含一下功能:

      • navigate:跳转到其他界面;
      • state:屏幕的当前state;
      • setParams: 改变路由的params;
      • goBack:关闭当前屏幕;
      • dispatch:向路由发送一个action;
      • addListener:订阅导航生命周期的更新;
      • isFocused:true 标识屏幕获取了焦点;
      • getParam:获取具有回退的特定参数;
      • dangerouslyGetParent: 返回父导航器;


      StackNavigator的navigation的额外功能

           当且仅当当前 navigator 是 stack navigator 时,this.props.navigation 上有一些附加功能。这些函数是 navigate 和 goBack 的替代方法,你可以使用任何你喜欢的方法。这些功能是:

      • this.props.navigation
        • push- 导航到堆栈中的一个新的路由
        • pop - 返回堆栈中的上一个页面
        • popToTop- 跳转到堆栈中最顶层的页面
        • replaite-用新路由替换当前路由
        • reset- 擦除导航器状态并将其替换为多个操作的结果
        • dismiss - 关闭当前栈

   

       使用navigate进行界面之间的跳转

       navigation.navigate ({routeName, params, action, key}) 或 navigation navigate(routeName, params, action)

           routeName:要跳转到的界面的路由名,也就是在导航其中配置的路由名;

           params:要传递给下一个界面的参数;

           action:如果该界面是一个navigator的话,将运行这个sub-action;

           key:要导航到的路由的可选标识符。如果已存在,将后退到此路由;

export const AppStackNavigator = createStackNavigator ({
    HomeScreen: {
        screen: HomeScreen
    },
    Pagel: {
        screen: Page1
    })

class HomeScreen extends React. Component {
    render () {
        const {navigate} = this.props.navigation;
        
        return (
            <View>
                ‹Text>This is HomeScreen</Text>
                ‹Button
                    onPress=(() => navigate( 'Pagel', {name: 'Devio'7)}
                    title="Go to Pagel"
                />
            </View>
        )
    }
}

       

       使用state的params

           可以通过this.props.state.params来获取通过 setParams(),或 navigation.navigate()传递的参数。

‹Button
    title={params.mode === ‘edit,?‘保存’:'编辑'}
    onPress=1( =>
        setParams ({mode: params-mode === 'edit' ? " : 'edit'})}
/>
<Button
    title="Go To Pagel"
    onPress={() => {
        navigation.navigate( 'Pagel', { name: 'Devio' });
    }}
const {navigation} = this.props;
const {state, setParams} = navigation;
const {params} = state;
const showText = params.mode === 'edit'?'正在编辑’:'编辑完成’;



      使用setParams 改变route params

       setParams: function setParams(params):我们可以借助 setParams 来改变route params,比如,通过 setParams 来更新页面顶部的标题,返回按钮等;


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


       使用goBack返回到上一页面或指定页面

           goBack:function goBack(key):我们可以借助goBack返回到上一页或者路由栈的指定页面。

               其中 key 表示你要返回到页面的页面标识如 id-1517035332238-4,不是routeName。

               可以通过指定页面的 navigation.state.key 来获得页面的标识。

               key非必传,也可传null。

           navigation.state {params: {...}, key: "id-1517035332238-4", routeName:"Pagel" }


       通过dispatch发送一个action

           dispatch:function dispatch(action):给当前界面设置action,会替换原来的跳转,回退等事件。

const resetAction = StackActions. reset({
    index: 0,
    actions: [
        NavigationActions.navigate({
            routeName: 'HomePage'
            params: {
                theme: theme,
                selectedTab: selectedTab
            },
        })
    ]
})
navigation.dispatch (resetAction)


评论(共0条)