react-router-dom v6.0新特性及路由守卫结合react-activation实现路由缓存

一、概述

v6相比v5,做了很多的优化。包括书写上更加的便捷,更加体现组件化思想。以往在处理路由嵌套和鉴权方面,v5的写法都靠各自开发人员去实现相对比较参差不齐。一下针对v6的配置做简单的介绍。

Github地址:GitHub - JavonHuang/react-router-v6

二、useRoutes

        v6中路由的设置采用hook的方式,有点像vue的router的实例化。

import {useRoutes} from "react-router-dom";
import { Suspense, lazy } from 'react'
const routes = [
  {
    path: '/',
    auth:false,
    component:lazy(() => import('./../page/login/Login'))
  },
  {
    path: '/Portal',
    auth:true,
    component:lazy(() => import('../page/portal/Portal')),
    children: [
      { 
        path: '/Portal/Home',
        auth:true,
        component:lazy(() => import('../page/home/Home'))
      },
      { path: '/Portal/Test/:id',
        auth:true,
        component:lazy(() => import('../page/test/Test'))
      },
      { 
        path: '/Portal/*',
        auth:false,
        component:lazy(() => import('../page/error/NotFound'))
      }
    ]
  },
  { 
    path: '*',
    auth:false,
    component:lazy(() => import('../page/error/NotFound'))
  },
 { 
    path: '/redirect',
    auth:false,
    component: lazy(() => import('../page/Redirect/Redirect')),
  }
]

//根据路径获取路由
const checkAuth = (routers:any, path:String)=>{
  for (const data of routers) {
    if (data.path==path) return data
    if (data.children) {
      const res:any = checkAuth(data.children, path)
      if (res) return res
    }
  }
  return null
}

// 路由处理方式
const generateRouter = (routers:any) => {
  return routers.map((item:any) => {
    if (item.children) {
      item.children = generateRouter(item.children)
    }
    item.element = <Suspense fallback={
      <div>加载中...</div>
    }>
      {/* 把懒加载的异步路由变成组件装载进去 */}
      <item.component />
    </Suspense>
    return item
  })
}

const Router = () => useRoutes(generateRouter(routes))
const checkRouterAuth = (path:String)=>{
  let auth = null
  auth = checkAuth(routes,path)
  return auth
}
export{ Router,checkRouterAuth}

路由嵌套

        v6中提供Outlet组件,用于预留坑渲染嵌套路由页面,是开发更加简单便捷

import './portal.scss'
import LeftSide from './LeftSide'
import TopHeader from './TopHeader'
import RouterBeforeEach from './../../routes/RouterBeforeEach'

const Portal =()=>{
  return (
    <div className="portal">
      <div className="portal-left">
        <LeftSide/>
      </div>
      <div className="portal-right">
        <TopHeader></TopHeader>
        <RouterBeforeEach/>
      </div>
    </div>
  );
}

export default Portal
import {useNavigate,useLocation,useResolvedPath } from "react-router-dom";
import { Outlet } from 'react-router-dom'
import {checkRouterAuth} from './index'
import {useEffect,useState} from 'react'
const RouterBeforeEach = ()=>{
  const navigate = useNavigate()
  const location = useLocation()
  const [auth,setAuth] = useState(false)
  useEffect(()=>{
    let obj = checkRouterAuth(location.pathname)
    let blLogin =sessionStorage.getItem('login')
    if(obj && obj.auth && blLogin=='false'){
      setAuth(false)
      navigate('/', {replace: true})
    }else{
      setAuth(true)
    }
  },[])
  return auth?<Outlet/>:null
} 

export default RouterBeforeEach

在挂在处渲染路由页面

import ReactDOM from 'react-dom';
import {BrowserRouter} from "react-router-dom";
import './index.css';
import {Router} from './routes/index'
ReactDOM.render(
  <BrowserRouter>
    <Router/>
  </BrowserRouter>,
  document.getElementById('root')
);

至此页面路由配置就完成了,相比以往版本的方式简单了许多。对新手更加的友好,特别对Vue的发开人员转向更加的友好

二、路由鉴权

        这里我新建了一个RouterBeforeEach组件,在渲染嵌套路由的时候,对需要鉴权的路由进行判断,不满足则跳转到登录页。

        

import {useNavigate,useLocation,useResolvedPath } from "react-router-dom";
import { Outlet } from 'react-router-dom'
import {checkRouterAuth} from './index'
import {useEffect,useState} from 'react'
const RouterBeforeEach = ()=>{
  const navigate = useNavigate()
  const location = useLocation()
  const [auth,setAuth] = useState(false)
  useEffect(()=>{
    let obj = checkRouterAuth(location.pathname)
    let blLogin =sessionStorage.getItem('login')
    if(obj && obj.auth && blLogin=='false'){
      setAuth(false)
      navigate('/')
    }else{
      setAuth(true)
    }
  },[])
  return auth?<Outlet/>:null
} 

export default RouterBeforeEach

三、路由参数获取

import {useSearchParams,useLocation ,useParams } from "react-router-dom";
const Test = ()=>{
  const [searchParams, setSearchParams] = useSearchParams()
  console.log(searchParams.get('id'))
  const params = useParams()
  const location =useLocation()
  console.log(params)
  console.log(location)
  return(
    <>
      测试
    </>
  )
}

export  default Test

最终效果

四、路由重定向

在routes路由配置文件添加一个重定向路由

 { 
    path: '/redirect',
    auth:false,
    component: lazy(() => import('../page/Redirect/Redirect')),
  }

编写重定向组件,在组件内部实现路由的跳转,从而实现路由的重定向

import { useNavigate } from "react-router-dom";
import { useEffect } from "react";
const Redirect=(props:any)=> {
  let navigate = useNavigate();
  useEffect(() => {
    navigate("/Portal/Home");
  });
  return <></>;
}

export default Redirect

该方案是由官方提供的,详情可以参考官方文档

五、使用react-activation实现路由缓存

安装包:react-activation

npm install react-activation

在入口处使用<AliveScope>组件包裹页面

import ReactDOM from 'react-dom';
import {BrowserRouter} from "react-router-dom";
import './index.css';
import {Router} from './routes/index'
import { AliveScope } from 'react-activation'
ReactDOM.render(
  <BrowserRouter>
    <AliveScope> 
      <Router/>
    </AliveScope>
  </BrowserRouter>,
  document.getElementById('root')
);

注册路由时,将需要缓存的页面使用<KeepAlive>包裹,这个组件必须设置id,否则缓存不生效。id要是唯一的,因为这个缓存时依据id实现的。


// 路由处理方式
const generateRouter = (routers:any) => {
  return routers.map((item:any) => {
    if (item.children) {
      item.children = generateRouter(item.children)
    }
    item.element = <Suspense fallback={
      <div>加载中...</div>
    }>
      {/* 把懒加载的异步路由变成组件装载进去 */}
      <KeepAlive id={item.path}>
        <item.component />
      </KeepAlive>
    </Suspense>
    return item
  })
}

  • 18
    点赞
  • 96
    收藏
    觉得还不错? 一键收藏
  • 15
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值