React路由ReactRouter6

V6路由新增了一些东西,也做了一些替换,路由配置上跟vue更加相似,值得一提的是,react官方提倡函数组件,所以这个例子将使用函数组件说明。
第一步安装路由

npm install react-router-dom

将会自动安装V6版本的路由。首先还是分清导航区和路由组件展示区,整理好布局
在这里插入图片描述

左边的为导航区,右边为路由组件展示区,所以在APP组件里依然是定义路由链接

import {NavLink,Link} from 'react-router-dom'

NavLink和v5一样 定义高亮

          <NavLink to="/about" className="list-group-item">About</NavLink>
          <NavLink to="/home" className="list-group-item">Home</NavLink>

接下来就是和v5一样注册路由,注意这里跟v5不一样的是 v5注册使用Switch包裹,V5如下

 <Switch>
           <Route path='/about' component={About}></Route>
           <Route path='/home' component={Home}></Route>
 </Switch>

V6新引进了Routes,并取代了Switch,组件的定义也不一样,element

 <Routes> 
           <Route path="/about" element={<About/>}></Route> 
           <Route path="/home" element={<Home/>}></Route> 
</Routes> 

这里重定向也改变了 v5是Redirect

  <Switch>
            <Route path='/about' component={About}></Route>
            <Route path='/home' component={Home}></Route>
            <Redirect to="/about"></Redirect>
           </Switch>

V6用的是Navigate

 <Routes> 
           <Route path="/about" element={<About/>}></Route> 
           <Route path="/home" element={<Home/>}></Route> 
           <Route path="/" element={<Navigate to="/about"/>}></Route>
</Routes> 

也可以修改NavLink高亮样式

    <NavLink to="/about" className={({isActive})=>isActive ? "list-group-item myActive":"list-group-item"}>About</NavLink>

myActive是自己定义的高亮样式
在这里插入图片描述

嵌套路由

嵌套路由更靠近vue路由的规则,用一个useRoutes来把一系列匹配规则生成路由,可以自定义一个routes/index.js文件,定义路由


import Home from "../pages/Home";
import About from "../pages/About";
import News from "../pages/News";
import Message from "../pages/Message";
import Detail from "../pages/Detail";
import { Navigate } from "react-router-dom";
const routes= [
    {
        path:"/home",
        element:<Home/>,
        children:
        [
            {
                path:"news",
                element:<News/>
            },
            {
                // 子路由不要跟/
                path:"message",
                element:<Message/>,
                children:[
                    {
                        // 传递params参数需要声明接收,这里跟vue一样。也跟react路由v5一样
                        // path:'detail/:id/:title/:content',
                        // 接收search和state参数 跟vue的query一样 跟react路由v5
                        path:'detail',
                        element:<Detail/>
                    }
                ]
            },
            {
                path:"",
                element:<Navigate to="news" />
            }
        ]
    },
    {
        path:"/about",
        element:<About/>
    },
    {
        path:"/",
        element:<Navigate to="/about"/>,
    },
]
export default routes

注意和vue对比

  routes : [
        {
            path:"/about",
            component:AboutCom
       },
        {
            path:"/home",
            component:HomeCom,
            children:[
                {
                   //  path:'/news',这里的/一定要删除是个坑,不然子路由组件渲染不出来
                   path:'news',
                    component:NewCom
                },
                {
                   // path:'/message',这里的/一定要删除是个坑,不然子路由组件渲染不出来
                   path:'message',
                   component:MessageCom,
                   children:[
                       {
                           //传递params参数 需要路由定义时声明
                           // path:"detail/:id/:title/:content",
                           //传递query参数不需要声明
                           path:"detail",
                           component:DetailCom,
                           name:'xiangqing' ,  
                           props(route){
                               console.log(route)
                               const {id,title,content} = route.query
                               return {id,title,content}
                           }        
                        }
                   ]
               },
            ]
           },
       ]
})

基本一致!!!
子路由的路由链接

    <NavLink className="list-group-item" to="news">News</NavLink>
    <NavLink className="list-group-item" to="message">Message</NavLink>

注意不写/
然后导出这个routes,在根组件引入 使用useRoutes生成路由注册

import {NavLink,useRoutes} from 'react-router-dom'
import routes from "./routes";
function App() {
  const element = useRoutes(routes)
       其他代码
        {/* 注册路由 这个地方是之前<Routes>注册路由占的difang*/}
        {element}

  );
}

export default App;

子路由匹配显示需要一个Outlet占位,对比vue的router-view

import {Outlet} from 'react-router-dom'
    这里是匹配到路由时,组件所在的位置
    <Outlet/>

路由传参

跟V5一样,三种传参方式 params、search、state

传递params参数

跟V5一样的

<li key={msg.id}><Link to={`detail/${msg.id}/${msg.title}/${msg.content}`}>{msg.title}</Link></li>

同意需要声明接收

  {
                        // 传递params参数需要声明接收,这里跟vue一样。也跟react路由v5一样
                        path:'detail/:id/:title/:content',
                        element:<Detail/>

在取params时需要借助useParams()

import { useParams } from 'react-router-dom'
const x = useParams()
传递search参数

传递跟V5一样,不需要声明接收

<li key={msg.id}><Link to={`detail/?id=${msg.id}&title=${msg.title}&content=${msg.content}`}>{msg.title}</Link></li>

    {
                        // 传递params参数需要声明接收,这里跟vue一样。也跟react路由v5一样
                        // path:'detail/:id/:title/:content',
                        // 接收search和state参数 跟vue的query一样 跟react路由v5
                        path:'detail',
                        element:<Detail/>
                    }

在取search时需要借助useSearchParams()

import { useSearchParams } from 'react-router-dom'
 const [search]=useSearchParams()
   const id = search.get("id")
传递state参数
     <li key={msg.id}><Link to="detail" state={{id:msg.id,title:msg.title,content:msg.content}}>{msg.title}</Link></li>

这是V5方式,不一样

 <li key={msgObj.id}><Link to={{pathname:'/home/message/detail',state:{id:msgObj.id,title:msgObj.title}}}>{msgObj.title}</Link></li>

不需要声明接收

    {
                        // 传递params参数需要声明接收,这里跟vue一样。也跟react路由v5一样
                        // path:'detail/:id/:title/:content',
                        // 接收search和state参数 跟vue的query一样 跟react路由v5
                        path:'detail',
                        element:<Detail/>
                    }

取state,借助useLocation()

import { useLocation } from 'react-router-dom'
 const x= useLocation()
 const {id,title,content} = x.state

编程式路由

V6的编程式路由借助useNavigate()

import {useNavigate} from 'react-router-dom'
 const navigate = useNavigate()

定义函数

function pushShow(msg){
   navigate('detail',{
     replace:false,
     state:{
       id:msg.id,
       title:msg.title,
       content:msg.content
     }
   })
  }
     <button onClick={()=>pushShow(msg)}>push查看</button>

这里涉及到传值 msg 所以是一个回调。
这个创建出来的navigate可以在任何组件实现编程式路由跳转,之前的V5一般组件里不能操作路由,因为它不是路由组件,没有history来调用API,如果非得用,需要withRouter包起来才可以实现,V6的navigate就没有这个问题,比如在一个一般组件Header里也可以实现路由跳转
在一般组件里引入

import { useNavigate } from 'react-router-dom'
export default function Header() {
   const navigate = useNavigate()
   function back(){
       navigate(-1)
   }
   function forward(){
       navigate(1)
   }
  return (
    <div> 
           <button onClick={back}>后退</button>&nbsp;
      <button onClick={forward}>前进</button>
      <div className="page-header"><h2>React Router Demo</h2></div>
   
    </div>
  )
}

这样就行了!

补充

useInRouterContext()—是否处于路由上下文环境
我们的App组件由BrowserRouter包围 那么他就是处于路由上下文环境 useInRouterContext()-为true
useNavigationType():返回当前的导航类型(用户是如何来到 用的是push还是replace 还是pop当前页面的)
返回值:POP、PUSH、REPLACE
备注:POP是指在浏览器直接打开这个路由组件(刷新页面)
useOutLet:用来呈现当前路由

const result = useOutlet()
console.log(result)

如嵌套路由没挂载 为false
如果挂载了,就展示这个路由对象
useResolvePath:作用给定一个url解析其中的path、search、hash值

useResolvePath('/user?id=001&name="tom#qwe')
Logo

前往低代码交流专区

更多推荐