React自定义路由以及路由守卫


title: React自定义路由以及路由守卫
date: 2022-10-08 21:39:17
tags:

  • React
  • 框架
  • 路由
    categories:
  • 框架
  • React

React自定义路由以及路由守卫

react路由v6版本提供了和Vue相像的路由表,但是相比Vue还是少了一点东西。官方所谓的“提供更多自由度”好是好。但我觉得太高的自由度对于开发来说效率上会大大折扣。重复性的造轮子倒不如使用提供的。。。

Vue中的路由

Vue提供的现成的路由Api方便了对路由的监听,在这两个钩子中可以对路由进行常用的 鉴权 等操作…

特别方便

// ...路由表
const routes = [
// ...
  {
    path: '*',
    component: () => import('@/components/common/404/Error.vue'),
    meta: {
      title: '404-s.kr'
    },
  },
// ...
]

// 生成路由对象
const router = new VueRouter({
  mode: 'history',
  routes,
  scrollBehavior(to, from, savedPosition) { // 解决vue页面跳转只有页面不是在顶部的问题
    // savedPosition 会在你使用浏览器前进或后退按钮时候生效
    if (savedPosition) {
      return {
        selector: savedPosition
      } 
    } else {
      return { x: 0, y: 0 }
    }
  }
})

//挂载路由导航守卫
router.beforeEach((to, from, next) => {
	// 路由跳转开始
})

router.afterEach((to, from) => {
	// 路由跳转完毕
})

React路由

在React中,Router v5版本没有路由表这种东西,需要自己写等…

但在v6版本中可以配置路由表,通过useRoutes(routes)可以生成v5当中的路由配置

V6版本当中要自己封装一套类useRoutes(routes)生成路由配置

路由的配置要根据情况!直接上代码:

// React 组件懒加载

// 封装快速导入工具函数
const lazyLoad = (moduleName: string) => {
    NProgress.start() // 显示进度条
    const Module = lazy(() => import(`pages/${moduleName}`));
    return <Module></Module>;
};

// 路由鉴权组件
// 高阶组件--将传入的路由组件进行鉴权判定
const Appraisal = ({ children }: any) => {
    if (!getCookie("userinfo")) {
        // 判断本地 是否 存有 Cookie
        // 如果没有 就 重定向到登陆页面
        message.warning('请先登录~');
        return <Navigate to="/login" replace />;
    } else {
        return children
    }
};

interface Router {
    path: string, // 路由路径
    children?: Array<Router>,  // 子路由
    element: any, // 路由页面
    auth?: boolean // 需要路由鉴权
}

const routes: Array<Router> = [
    // ...
    
    // 主页
    {
        path: '/home',
        element: <Home></Home>,
    },
    // 搜索
    {
        path: '/search',
        element: lazyLoad('Search'),
        children: [
            {
                path: 'product/:name',
                element: lazyLoad('Product')
            },
            {
                path: 'activity',
                element: lazyLoad('Activity')
            },
            {
                path: 'show',
                element: lazyLoad('Show')
            },
            {
                path: '/search',
                element: <Navigate to="/search/product"></Navigate>
            }
        ]
    },
    // 底部路由跳转
    {
        path: '/about', // 关于我们
        element: lazyLoad('About')
    },
    // ...

];

// 通过 MyRouter 函数动态生成路由配置
// 这种 路由生成仅限两层路由
const MyRouter = () => {
    return (
        <Suspense fallback={<Loading />}>
            <Routes>
                {
                    routes.map((item, index) => {
                        // 判断是否需要鉴权
                        if (item.auth) {
                            return <Route key={index} path={item.path} element={<Appraisal>{item.element}</Appraisal>}></Route>
                        }
                        // 判断是否有子路由
                        return (item.children ?
                            <Route key={index} path={item.path} element={item.element}>
                                {
                                    item.children.map((e, i) =>
                                        <Route key={i} path={e.path} element={e.element} />
                                    )
                                }
                            </Route> :
                            <Route key={index} path={item.path} element={item.element}></Route>
                        )
                    })
                }
            </Routes>
        </Suspense>
    )
}

export default MyRouter;

情况二

有些情况下,我们所展示的页面有些是需要公共底部导航的,但是有些页面是不需要的。我就需要根据实际情况配置路由;(此配置没有路由守卫)

import { lazy,Suspense } from 'react'
import App from 'App'
import {
    BrowserRouter,
    Routes,Route,
    Navigate
} from "react-router-dom";


interface routeType{
  path?:string
  element?:React.ReactNode
  children?:Array<routeType>
}

// 定义数组每一项的接口
interface IRoute {
  path:string;
  component:React.FC;
  children?:Array<IRoute>
}

const router_arr:IRoute[] = [
  {
      path:"/",
      component:App,
      children:[
          {path:"/home",component:lazy(()=>import("pages/Home"))},
          {path:"/sort",component:lazy(()=>import("pages/Sort"))},
          {path:"/shopcar",component:lazy(()=>import("pages/ShopCar"))},
          {path:"/usercenter",component:lazy(()=>import("pages/UserCenter"))},
          {path:"/",component:lazy(()=>import("pages/Home"))},
      ]
  },
  {
      path:"/login",
      component:lazy(()=>import("pages/Login"))
  },
  {
      path:"/search",
      component:lazy(()=>import("pages/Search"))
  },
  {
      path:"/register",
      component:lazy(()=>import("pages/Register"))
  },
  {
      path:"*",
      component:lazy(()=>import("pages/404"))
  }
]


const MyRouter = ()=>(
      <BrowserRouter>
        <Suspense fallback={<h1></h1>}>
        <Routes>{
        router_arr.map((item,index)=>{
            if (item.path==='*') {
                return <Route key={index} path={item.path} element={<item.component/>}></Route>
            }
            return (item.children ?
            <Route key={index} path={item.path} element={<item.component/>}>
                {
                    item.children.map((e,i)=>{
                        if (e.path === '/') {
                            return <Route key={i} path={e.path} element={<Navigate to="/home"/>}/>
                        }
                        return <Route key={i} path={e.path} element={<e.component/>}/>
                    })
                }
            </Route>:
            <Route key={index} path={item.path} element={<item.component/>}></Route>
        )})
        }</Routes> 
        </Suspense>   
      </BrowserRouter>
)

export default MyRouter

这种配置下的路由,就需要将配置到入口函数:

这种路由配置,可解决部分页面需要底部导航,而有些页面却不需要。就比如说登录页,注册页等等。。

import MyRouter from 'router/router';

const root = ReactDOM.createRoot(
  document.getElementById('root') as HTMLElement
);

root.render( 
  <MyRouter />
);

而App组件中就需要这样写:

...

function App() {
  return (
      <>
        <Outlet/>
        <FooterLink/>
      </>
  );
}

...

你可能感兴趣的:(React,react.js,javascript,前端)