美文网首页
记RN路由系统重构-react-navigation

记RN路由系统重构-react-navigation

作者: 腿毛怪丶叔叔 | 来源:发表于2023-11-07 14:33 被阅读0次

    记RN路由系统重构-react-navigation

    简单说明

    目前react-native项目中使用的路由是react-navigation,官方的路由只是简单的示例,页面过多后,App.tsx主页面需要复制粘贴许多RootStack.Screen,路由navigation需要逐层传递,当然也可以是实用useDispatchuseNavigationhooks获取,但为了方便管理和升级路由系统,封装了routers以及MRouters 管理类,部分完整代码直接拖到最后可以查看。

    路由系统改造主要是包括路由配置src/router.js、路由管理src/framework/MRouter.ts、页面使用src/app.tsx三部分

    路由配置src/router.js

    1.路由动画枚举animationType

    const animationType = {
      default: 'default',
      fade: 'fade',
      fade_from_bottom: 'fade_from_bottom',
      flip: 'flip',
      none: 'none',
      simple_push: 'simple_push',
      slide_from_bottom: 'slide_from_bottom',
      slide_from_right: 'slide_from_right',
      slide_from_left: 'slide_from_left'
    }
    

    2.路由屏幕屏幕方向枚举orientationType

    const orientationType = {
      default: 'default',
      all: 'all',
      portrait: 'portrait',
      portrait_up: 'portrait_up',
      portrait_down: 'portrait_down',
      landscape: 'landscape',
      landscape_left: 'landscape_left',
      landscape_right: 'landscape_right'
    }
    

    3.默认路由配置screenConfig

    const screenConfig: NativeStackNavigationOptions = {
      headerShown: true,
      headerShadowVisible: false,
      headerTitleAlign: 'center',
      headerBackTitle: '',
      headerBackVisible: false,
      headerBackTitleVisible: false,
      headerTintColor: '#3D3F43',
      animation: animationType.slide_from_right,
      orientation: orientationType.portrait,
      headerStyle: {
        backgroundColor: '#fff',
        // @ts-ignore
        borderBottomWidth: 0
      },
      headerTitleStyle: {
        fontSize: 18,
        fontWeight: '500',
        color: '#3D3F43'
      }
    };
    

    自定义HeaderTitlegetHeaderTitle

    const getHeaderTitle = (text) => {
      return (
        <View style={{
          height: 28,
          marginBottom: 8,
          // backgroundColor: '#f00',
          justifyContent: 'center',
          alignItems: 'center'
        }}>
          <UIText style={[{
            fontSize: 18,
            fontWeight: '500'
          }, { color: '#3D3F43' }]}>{text}</UIText>
        </View>
      );
    };
    

    screen option生成getOptions

    const getOptions = (param: NativeStackNavigationOptions) => {
      const options: NativeStackNavigationOptions = {
        ...screenConfig,
        ...param,
        headerLeft: () => <HeaderBackArrow />,
        headerTitle: () => getHeaderTitle(param.title || '')
      };
      return options;
    };
    

    路由配置对象routers

    路由中包括nameoptionscompenent三部分

    name代表当前路由名称

    options代表当前路由的配置,主要包括title``anmimation``headerShown``gestureEnabled等配置项,具体有哪些配置项参考NativeStackNavigationOptions

    component代表当前路由的组件

    const routers = {
      Login: { name: 'Login', options: getOptions({ animation: animationType.slide_from_bottom, headerShown: false }), component: Login },
      Info: { name: 'Info', options: getOptions({}), component: Info },
      Tabbar: { name: 'Tabbar', options: getOptions({ animation: animationType.slide_from_right }), component: Tabbar },
      Agreement: { name: 'Agreement', options: getOptions({}), component: Agreement },
      ...
    }
    

    路由管理src/framework/MRouter.ts

    1.路由ref设置

    let _navigator: any;
    
    /**
     * 设置路由ref
     * @param navigatorRef 路由ref
     */
    function setNavigator(navigatorRef: any) {
      _navigator = navigatorRef;
      logInfo('setNavigator');
    }
    

    2.打开新页面

    主要newPage参数使用,可开启新页面不会回跳旧页面

    /**
     * 打开一个新页面
     * @param name 路由名称
     * @param params 路由参数
     * @param newPage 是否开启新页面 默认false
     */
    function open(name: string, params?: any, newPage?: boolean) {
      let index = indexOfRouteByName(name);
      let route = getRouteInfoByName(name);
      let item: any = {
        key: route?.key || name,
        name: name,
        path: name,
        params: params || null
      };
      console.log('newPage', newPage, index);
      if (newPage || index === -1) item.key = name + generateRandom();
    
      _navigator.dispatch(CommonActions.navigate(item));
      logInfo('open', name);
    }
    

    3.重置路由栈

    /**
     * 将路由name重置到首页 并且清空路由栈
     * @param name 路由名称
     * @param params 路由参数
     */
    function home(name: string, params?: object) {
      try {
        let item = {
          name: name,
          path: name,
          params: params,
          key: name + generateRandom()
        };
    
        _navigator.dispatch(
          CommonActions.reset({
            index: 0,
            routes: [item]
          })
        );
      } catch (e) {
        errorHandler.noRoute(name);
      }
      logInfo('home', name);
    }
    

    4.路由替换

    /**
     * 将栈顶的路由替换为${name}路由
     * @param name 路由名称
     * @param params 路由参数
     */
    function replace(name: string, params?: any) {
      let routers = _navigator.getRootState().routes || [];
      let index = indexOfRouteByName(name);
      if (name && index > -1) {
        let item = {
          index,
          name: name,
          path: name,
          key: routers[index].key
        };
        if (index > -1) routers = routers.slice(0, index);
        routers.push(item);
        _navigator.dispatch(
          CommonActions.reset({
            index: 0,
            routes: routers
          })
        );
      } else {
        routers.pop();
        let item = {
          name: name,
          params: params,
          path: name,
          key: name + generateRandom()
        };
        routers.push(item);
        _navigator.dispatch(
          CommonActions.reset({
            index: 0,
            routes: routers
          })
        );
      }
      logInfo('replace', name);
    }
    

    路由返回

    主要name参数,不传就默认往回跳转一页,传了就调用open方法跳转到原来就有的那一页

    /**
     * 路由回退
     * @param name 路由名称
     * @param params 回调参数
     */
    function back(name?: string, params?: any) {
      let index = -1;
      let route = null;
      if (name) {
        index = indexOfRouteByName(name);
        route = getRouteInfoByName(name);
      } else {
        route = _navigator.getRootState().routes[_navigator.getRootState().routes.length - 1];
      }
    
      if (index > -1) {
        open(route.name, params);
      } else {
        close();
      }
    
      params &&
        _navigator.dispatch(
          CommonActions.setParams({
            params: params,
            key: route && route.key,
            source: route && route.key
          })
        );
    
      logInfo('back', name);
    }
    

    关闭当前路由

    /**
     * 关闭当前路由
     */
    function close() {
      if (_navigator.canGoBack()) {
        _navigator.dispatch(CommonActions.goBack());
      }
      logInfo('close');
    }
    

    获取路由name在路由栈中当前的位置

    查找的顺序是从后往前找

    /**
     * 获取路由name在路由栈中当前的位置  从后往前查找
     * @param name 路由名称
     * @returns 返回index
     */
    function indexOfRouteByName(name: string) {
      let routers = _navigator.getRootState().routes || [];
      let index = -1;
      let routeIndex = routers.length;
      console.log('indexOfRouteByName', name, routeIndex, routers);
      while (routeIndex > 0) {
        routeIndex--;
        let route = routers[routeIndex];
        if (route.name === name) {
          index = routeIndex;
          break;
        }
      }
      return index;
    }
    

    根据页面名字获取页面所在路由的信息

    /**
     * 根据页面名字获取页面所在路由的信息
     * @param  {String} name 页面名字
     * @return {{name,key,path,params}}      页面所在路由,如果没有则返回 null
     */
    function getRouteInfoByName(name: string) {
      let routers = _navigator.getRootState().routes || [];
      let routeIndex = routers.length;
      while (routeIndex) {
        routeIndex--;
        let route = routers[routeIndex];
        if (route.name === name) {
          return route;
        }
      }
      return routers[routers.length];
    }
    

    App.tsx配置

    1.路由navigationRef对象获取传递

    function App() {
      const navigationRef = useNavigationContainerRef();
    
      return (
        <SafeAreaProvider>
          <NavigationContainer ref={navigationRef}>
            <NavigatorFn navigationRef={navigationRef} />
          </NavigationContainer>
        </SafeAreaProvider>
      );
    }
    

    2.MRouter初始化

    useEffect(() => {
        MRouter.setNavigator(navigationRef);
        ...
      }, []);
    

    3.路由动态生成

    <RootStack.Navigator
            // initialRouteName="Root"
            // backBehavior="history"
            screenOptions={{
              headerShown: false,
              orientation: 'portrait'
            }}>
            {routers &&
              Object.keys(routers).map((key, index) => {
                return (
                  <RootStack.Screen
                    key={index}
                    name={routers[key].name}
                    options={routers[key].options}
                    getComponent={() => routers[key].component}
                  />
                );
              })}
     </RootStack.Navigator>
    

    4.根据现有项目改造

    useEffect(() => {
        AsyncStorage.getItem('token')
          .then(token => {
            dispatch(setToken({ token }));
            if (!token) {
              MRouter.home(routers.Login.name);
            }
          })
          .catch(err => {
            MRouter.home(routers.Login.name);
          });
      }, [token]);
    
      // if (isLoading) {
      //   return <></>;
      // }
      useEffect(() => {
        switch (status) {
          case 'login': // 进入登陆
            MRouter.home(routers.Login.name);
            break;
          default:
            MRouter.home(routers.Loading.name);
            break;
        }
      }, [status]);
    

    MRouter使用补充说明

    MRouter使用在任何页面和组件都可以直接使用,不用层层传递

    MRouter提供了基本所有场景的使用方式

    MRouter与原来navigationnavigatereplace等方法兼容,路由栈是同一个可以配合使用

    MRouter使用说明

    //MRouter打开新页面
    //通过字符串Login
    MRouter.open(‘Login’)   
    //通过路由系统的name
    MRouter.open(routers.Login.name)   
    //通过第二参数传递params
    MRouter.open(routers.Login.name, { name: 'abc', key: 1 })  
    //通过第二参数传递params 通过第三参数确认是否开启新页面
    //第三参数默认false,当前路由栈存在该页面时会自动跳转回存在的页面 设置为true,每次都开启新页面
    MRouter.open(routers.Login.name, { name: 'abc', key: 1 }, true)  
    
    
    //参数获取
    //Component获取 直接从this.props中获取
    const { params } = this.props;
    const { name, key } = params;
    //从hooks中获取
    const route = useRoute();
    const name = _.get(route, 'params.name', 'Demo Params');
    
    
    //MRouter重置当前路由栈 并将页面为某个页面 同open可设置参数
    MRouter.home(routers.Login.name)
    MRouter.home(routers.Login.name, { key: 2, name: 'bcd' })
    
    
    //MRouter替换路由栈顶的路由
    MRouter.replace(routers.Login.name)
    MRouter.replace(routers.Login.name, { key: 2, name: 'bcd' })
    
    
    //MRouter关闭页面
    //默认返回上一页
    MRouter.back()
    //返回路由名称为name的页面 可传递参数
    //默认调用的是open方法 如果页面存在就返回到存在的页面 可传递参数
    MRouter.back(routers.Login.name)
    MRouter.back(routers.Login.name, { key: 2, name: 'bcd' })
    

    部分代码示例

    MRouter.ts

    import { CommonActions } from '@react-navigation/native';
    import errorHandler from './error/errorHandler';
    import { routers } from 'router/router';
    import { generateRandom } from 'utils';
    import { NativeModules } from 'react-native';
    
    let _navigator: any;
    
    /**
     * 设置路由ref
     * @param navigatorRef 路由ref
     */
    function setNavigator(navigatorRef: any) {
      _navigator = navigatorRef;
      logInfo('setNavigator');
    }
    
    /**
     * 将栈顶的路由替换为${name}路由
     * @param name 路由名称
     * @param params 路由参数
     */
    function replace(name: string, params?: any) {
      let routers = _navigator.getRootState().routes || [];
      let index = indexOfRouteByName(name);
      if (name && index > -1) {
        let item = {
          index,
          name: name,
          path: name,
          params: params,
          key: name + generateRandom()
        };
        if (index > -1) routers = routers.slice(0, index);
        routers.push(item);
        _navigator.dispatch(
          CommonActions.reset({
            index: 0,
            routes: routers
          })
        );
      } else {
        routers.pop();
        let item = {
          name: name,
          params: params,
          path: name,
          key: name + generateRandom()
        };
        routers.push(item);
        _navigator.dispatch(
          CommonActions.reset({
            index: 0,
            routes: routers
          })
        );
      }
      logInfo('replace', name);
    }
    
    /**
     * 打开一个新页面
     * @param name 路由名称
     * @param params 路由参数
     * @param newPage 是否开启新页面 默认false
     */
    function open(name: string, params?: object, newPage?: boolean) {
      let index = indexOfRouteByName(name);
      let route = getRouteInfoByName(name);
      let item: any = {
        key: route?.key || name,
        name: name,
        path: name,
        params: params || null
      };
      // console.log('newPage', newPage, index);
      if (newPage || index === -1) item.key = name + generateRandom();
    
      _navigator.dispatch(CommonActions.navigate(item));
      logInfo('open', name);
    }
    
    /**
     * 将路由name重置到首页 并且清空路由栈
     * @param name 路由名称
     * @param params 路由参数
     */
    function home(name: string, params?: object) {
      try {
        let item = {
          name: name,
          path: name,
          params: params,
          key: name + generateRandom()
        };
    
        _navigator.dispatch(
          CommonActions.reset({
            index: 0,
            routes: [item]
          })
        );
      } catch (e) {
        errorHandler.noRoute(name);
      }
      logInfo('home', name);
    }
    
    /**
     * 路由回退
     * @param name 路由名称
     * @param params 回调参数
     */
    function back(name?: string, params?: any) {
      let index = -1;
      let route = null;
      if (name) {
        index = indexOfRouteByName(name);
        route = getRouteInfoByName(name);
      } else {
        route = _navigator.getRootState().routes[_navigator.getRootState().routes.length - 1];
      }
    
      if (index > -1) {
        open(route.name, params || route.params);
      } else {
        close();
      }
    
      params &&
        _navigator.dispatch(
          CommonActions.setParams({
            params: params,
            key: route && route.key,
            source: route && route.key
          })
        );
    
      logInfo('back', name);
    }
    
    //顶部路由名称
    function topPath() {
      return _navigator.getRootState().routes[0] || {};
    }
    
    //顶部路由名称
    function isTopPath(name: string) {
      const topRoute = _navigator.getRootState().routes[0] || {};
      return topRoute.name === name;
    }
    
    /**
     * 关闭当前路由
     */
    function close() {
      if (_navigator.canGoBack()) {
        _navigator.dispatch(CommonActions.goBack());
      }
      logInfo('close');
    }
    
    /**
     * 获取路由name在路由栈中当前的位置  从后往前查找
     * @param name 路由名称
     * @returns 返回index
     */
    function indexOfRouteByName(name: string, isPrev?: boolean) {
      let routers = _navigator.getRootState().routes || [];
      let index = -1;
      if (isPrev) {
        return routers.findIndex((item: any) => item.name === name);
      } else {
        let routeIndex = routers.length;
        // console.log('indexOfRouteByName', name, routeIndex, routers);
        while (routeIndex > 0) {
          routeIndex--;
          let route = routers[routeIndex];
          if (route.name === name) {
            index = routeIndex;
            break;
          }
        }
      }
    
      return index;
    }
    
    /**
     * 根据页面名字获取页面所在路由的信息
     * @param  {String} name 页面名字
     * @return {{name,key,path,params}}      页面所在路由,如果没有则返回 null
     */
    function getRouteInfoByName(name: string, isPrev?: boolean) {
      let routers = _navigator.getRootState().routes || [];
      let routeIndex = routers.length;
      if (isPrev) {
        return routers.find((item: any) => item.name === name);
      }
      while (routeIndex) {
        routeIndex--;
        let route = routers[routeIndex];
        if (route.name === name) {
          return route;
        }
      }
      return routers[routers.length];
    }
    
    /**
     * 获取当前的路由栈
     * @returns 返回路由栈
     */
    function getRouters() {
      return _navigator?.getRootState()?.routes;
    }
    /**
     * 打开android app设置页面
     */
    function openAppSetting() {
      return new Promise((resolve, reject) => {
        NativeModules.NativeRouter.openAppSetting();
      });
    }
    
    /**
     * 重新生成路由栈-只保留栈顶的路由和${name}路由
     * @param name 路由名称
     * @param params 路由参数
     */
    function replaceOthers(name: string, params?: object) {
      let routers = _navigator.getRootState().routes || [];
    
      const newRouters = routers.slice(0, 1);
      try {
        let item = {
          name: name,
          path: name,
          params: params,
          key: name + generateRandom()
        };
    
        _navigator.dispatch(
          CommonActions.reset({
            index: 0,
            routes: [...newRouters, item]
          })
        );
      } catch (e) {
        errorHandler.noRoute(name);
      }
      logInfo('replaceOthers', name);
    }
    /**
     * 回到路由栈中的第一个,并关闭所有其他路由
     */
    function popToTop() {
      let routers = _navigator.getRootState().routes || [];
      const newRouters = routers.slice(0, 1);
      try {
        _navigator.dispatch(
          CommonActions.reset({
            index: 0,
            routes: [...newRouters]
          })
        );
      } catch (e) {
        errorHandler.noRoute('popToTop');
      }
      logInfo('popToTop');
    }
    
    const logInfo = (type:string, msg?:string) => {
      console.log('msg', type, msg)
    }
    
    
    export default {
      home,
      open,
      replace,
      back,
      close,
      setNavigator,
      topPath,
      getRouters,
      openAppSetting,
      isTopPath,
      replaceOthers,
      popToTop,
    };
    

    ErrorHandler.js

    const noop = (e:Error,isFatal:Boolean) => { };
    
    export const setJSExceptionHandler = (customHandler = noop, allowedInDevMode = false) => {
        if (typeof allowedInDevMode !== "boolean" || typeof customHandler !== "function") {
            return;
        }
        const allowed = allowedInDevMode ? true : !__DEV__;
        if (allowed) {
            // !!! 关键代码
            // 设置错误处理函数
            global.ErrorUtils.setGlobalHandler(customHandler);
            // 改写 console.error,保证报错能被 ErrorUtils 捕获并调用错误处理函数处理
            console.error = (message, error) => global.ErrorUtils.reportError(error);
        }
    };
    
    export const getJSExceptionHandler = () => global.ErrorUtils.getGlobalHandler();
    
    export default {
        setJSExceptionHandler,
        getJSExceptionHandler,
    };
    

    generateRandom方法

    export const generateRandom = () => {
      return Math.random().toString(16).slice(2);
    };
    

    router.tsx

    import React from 'react';
    import { NativeStackNavigationOptions } from '@react-navigation/native-stack';
    import Login from 'pages/login/index';
    import HeaderBackArrow from 'components/HeaderBackArrow';
    import { UITitleText } from 'components/Text/Texts';
    import Loading from 'pages/loading';
    import { GestureResponderEvent } from 'react-native-modal';
    import MRouter from 'framework/MRouter';
    
    //屏幕动画枚举
    const animationType: any = {
      default: 'default',
      fade: 'fade',
      fade_from_bottom: 'fade_from_bottom',
      flip: 'flip',
      none: 'none',
      simple_push: 'simple_push',
      slide_from_bottom: 'slide_from_bottom',
      slide_from_right: 'slide_from_right',
      slide_from_left: 'slide_from_left'
    };
    
    //屏幕方向枚举
    const orientationType = {
      default: 'default',
      all: 'all',
      portrait: 'portrait',
      portrait_up: 'portrait_up',
      portrait_down: 'portrait_down',
      landscape: 'landscape',
      landscape_left: 'landscape_left',
      landscape_right: 'landscape_right'
    };
    
    //屏幕默认config
    // const screenConfig: NativeStackNavigationOptions = {
    const screenConfig: any = {
      headerShown: true,
      headerShadowVisible: false,
      headerTitleAlign: 'center',
      headerBackTitle: '',
      headerBackVisible: false,
      headerBackTitleVisible: false,
      headerTintColor: '#3D3F43',
      animation: animationType.slide_from_right,
      orientation: orientationType.portrait,
      headerStyle: {
        backgroundColor: '#fff',
        // @ts-ignore
        borderBottomWidth: 0
      },
      headerTitleStyle: {
        fontSize: 18,
        fontWeight: '500',
        color: '#3D3F43'
      }
    };
    let tempTime = 0;
    let clickNum = 0;
    const onWelcome = (e: GestureResponderEvent) => {
      // console.log('onWelcome', e.timeStamp);
      const time = e.timeStamp;
      if (tempTime === 0) {
        tempTime = e.timeStamp;
      } else {
        if (time - tempTime > 300) {
          tempTime = time;
          clickNum = 0;
          return;
        }
        clickNum++;
        tempTime = time;
    
        if (clickNum === 11) {
          // Toast.info('连续点击8次,进入隐藏页面');
          // if (REACT_NATIVE_ENV !== 'PRODUCTION') {
          // }
          MRouter.open(routers.Login.name);
          clickNum = 0;
          tempTime = 0;
          return;
        }
      }
    };
    
    //路由option
    const getOptions = (param: NativeStackNavigationOptions) => {
      const options: NativeStackNavigationOptions = {
        ...screenConfig,
        ...param,
        headerLeft: () => <HeaderBackArrow />,
        headerTitle: () => (
          <UITitleText onPress={onWelcome} suppressHighlighting={true}>
            {param.title || ''}
          </UITitleText>
        )
      };
      return options;
    };
    
    //在这里可以填写我们所需要的路由(页面) options可以配置我们对应的navigation配置
    const routers = {
      Loading: { name: 'Loading', options: getOptions({ headerShown: false }), component: Loading },
      Login: { name: 'Login', options: getOptions({ title: '关于我们' }), component: Login },
    };
    
    //导出路由
    export { routers };
    

    App.tsx

    // In App.js in a new project
    
    import React, { useEffect} from 'react';
    import { useAppSelector, useAppDispatch } from 'store/hook';
    import { NavigationContainer, useNavigationContainerRef } from '@react-navigation/native';
    import { createNativeStackNavigator } from '@react-navigation/native-stack';
    import { SafeAreaProvider } from 'react-native-safe-area-context';
    import MyStyleSheet from 'components/MyStyleSheet';
    import MRouter from 'framework/MRouter';
    import { routers } from 'router/router';
    
    const RootStack = createNativeStackNavigator();
    
    const NavigatorFn: React.FC<{ navigationRef: any }> = ({ navigationRef }) => {
      const dispatch = useAppDispatch();
      const { action, action_params } = useAppSelector(state => state.account);
    
      const openPage = (pageName: string) => {
        const params = action_params ? action_params : {};
        MRouter.home(pageName, params);
      };
    
      useEffect(() => {
        MRouter.setNavigator(navigationRef?.current);
      }, []);
    
    
      useEffect(() => {
        console.log('action', action);
        switch (action) {
          case 'login':
            openPage(routers.Tabbar.name);
            break;
          default:
            openPage(routers.Loading.name);
            // openPage(routers.Tabbar.name);
            break;
        }
      }, [action]);
    
      return (
        <>
          <RootStack.Navigator
            // initialRouteName="Root"
            // backBehavior="history"
            screenOptions={{
              headerShown: false,
              orientation: 'portrait'
            }}>
            {routers &&
              Object.keys(routers).map((key, index) => {
                return (
                  <RootStack.Screen
                    key={index}
                    name={routers[key].name}
                    options={routers[key].options}
                    getComponent={() => routers[key].component}
                  />
                );
              })}
          </RootStack.Navigator>
        </>
      );
    };
    
    function App() {
      const navigationRef = useNavigationContainerRef();
      const dispatch = useAppDispatch();
    
      return (
        <SafeAreaProvider>
          <NavigationContainer
            ref={navigationRef}
            onStateChange={state => {
              // 全局路由埋点
              // if (state) {
              //   const { routes } = state;
              //   if (routes?.length > 0) {
              //     let data: any = {};
              //     if (routes.length > 1) {
              //       const { name = '', key = '' } = routes[1];
              //       const { name: preName = '', key: preKey = '' } = routes[0];
              //       data.page_from = preName;
              //       data.page = name;
              //       data.page_from_key = preKey;
              //       data.page_to = name;
              //       data.page_to_key = key;
              //     } else {
              //       const { name, key } = routes[0];
              //       data.page_to = name;
              //       data.page_key_to = key;
              //     }
              //     TrackEventManager.trackEvent(TrackEventEnum.page_jump, {
              //       ...data,
              //       event: TrackEventEnum.page_jump,
              //       event_desc: '页面跳转',
              //       page: '页面'
              //     });
              //   }
              // }
            }}>
            <NavigatorFn navigationRef={navigationRef} />
          </NavigationContainer>
        </SafeAreaProvider>
      );
    }
    
    const styles = MyStyleSheet.create({
      header: {
        height: 28,
        marginBottom: 8,
        // backgroundColor: '#f00',
        justifyContent: 'center',
        alignItems: 'center'
      },
      headerTitle: {
        fontSize: 18,
        fontWeight: '500'
      },
    });
    
    export default App;
    

    结束语

    懂的都懂

    相关文章

      网友评论

          本文标题:记RN路由系统重构-react-navigation

          本文链接:https://www.haomeiwen.com/subject/hblfwdtx.html