React路由ReactRouter6
React路由ReactRouter6V6路由新增了一些东西,也做了一些替换,路由配置上跟vue更加相似,值得一提的是,react官方提倡函数组件,所以这个例子将使用函数组件说明。第一步安装路由npm install react-router-dom将会自动安装V6版本的路由。首先还是分清导航区和路由组件展示区,整理好布局左边的为导航区,右边为路由组件展示区,所以在APP组件里依然是定义路由链接i
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>
<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')
更多推荐
所有评论(0)