react-router-V5
一、路由模式
import {
HashRouter as RouterMode, // 路由别名
Route,
Switch,
Redirect,
NavLink
} from "react-router-dom"
HashRouter 表示hash模式的路由,有#号
BrowserRouter 表示history模式的路由,没有#号
二、Switch
Switch 组件可以用来包裹Route组件,这样匹配到路由之后,就不会继续匹配了。如果不使用该组件包裹,则会在匹配到之后,继续向下匹配。
<Switch>
<Route path="/login" component={Login}></Route>
<Route path="/home" component={Home}></Route>
<Redirect from="*" to="/login"></Redirect>
<Route component={NotFound}></Route>
</Switch>
三、Route 的属性
render 属性里面可以是一个函数,参数props可以提供history的路由相关的方法。在这个函数中可以做一些路由判断等,比如路由鉴权。
<Route
path="/home"
render={(props) => {
console.log(props)
}}
></Route>
exact 精确匹配,这个参数不能设置在有子路由的组件上,否则子路由不生效。
<Route path="/home" component={Home} exact></Route>
四、重定向-Redirect
<Redirect from="*" to="/login"></Redirect>
五、404组件
万能匹配
<Route component={NotFound}></Route>
六、路由嵌套
一级路由是Home组件
<Route path="/home" component={Home} ></Route>
二级路由写在Home组件里面的对应位置即可
<Switch>
<Route path="/home/page-a" component={PageA}></Route>
<Route path="/home/page-b" component={PageB}></Route>
<Redirect from="/home" to="/home/page-a"></Redirect>
</Switch>
七、声明式与编程式导航
声明式导航
a 标签也可以,但是设置高亮很麻烦
<a href="#/home">home</a>
<a href="#/login">login</a>
内置active类名,直接设置高亮即可
<NavLink to="/home">home</NavLink>
<NavLink to="/login">login</NavLink>
编程式导航
1. js方式
import React from "react"
const Item = () => {
return (
<div>
Item
<button
onClick={() => {
window.location.hash = "#/login"
}}
>
跳转
</button>
</div>
)
}
export default Item
2. 使用 props
被路由相关组件包裹的组, 可以直接通过this.props.history 进行调用相关方法。
<RouterMode>
<Switch>
<Route path="/login" component={Login}></Route>
<Route path="/home" component={Home}></Route>
<Redirect from="*" to="/login"></Redirect>
<Route component={NotFound}></Route>
</Switch>
</RouterMode>
import React, { Component } from "react"
export default class Login extends Component {
render() {
console.log(this.props.history)
return <div>Login</div>
}
}
import React from "react"
const Home = (props) => {
console.log(">>>", props) // 这个props 因为被route组件包裹,所以存在hsitory对象
return (
<div>
Home
<Item />
</div>
)
}
export default Home
withRouter
某些情况下,我们需要跳转,但是又拿不到history对象,需要使用高阶组件 withRouter 给需要路由跳转的组件添加history对象
import React from "react"
import { withRouter } from "react-router-dom"
const Item = (props) => {
console.log(props)
return <div>Item</div>
}
export default withRouter(Item)
3. 使用 useHistory
import { useHistory } from "react-router-dom"
const Home = () => {
const history = useHistory()
return (
<div>
<button
onClick={() => {
history.replace("/home/page-b")
}}
>
按钮
</button>
Home
<Switch>
<Route path="/home/page-a" component={PageA}></Route>
<Route path="/home/page-b" component={PageB}></Route>
<Redirect from="/home" to="/home/page-a"></Redirect>
</Switch>
</div>
)
}
八、动态路由
<RouterMode>
<Switch>
// 这里设置的就是动态路由
<Route path="/login/:id" component={Login}></Route>
<Route path="/home" component={Home}></Route>
<Redirect from="*" to="/login"></Redirect>
<Route component={NotFound}></Route>
</Switch>
</RouterMode>
// 编程式导航跳转
<button
onClick={() => {
history.replace("/login/123")
}}
>
按钮--go-login
</button>
// 声明式导航跳转
<NavLink to="/login/123">login</NavLink>
跳转到login页面的时候,可以在props里面的match里面的params里面拿到,实现路由传参。
九、路由传参
<Route path="/login" component={Login}></Route>
query 传参
通过这个传参方式,可以在history.location.query 里面获取到参数。
history.replace({ pathname: "/login", query: { id: 123 } })
history.push({ pathname: "/login", query: { id: 123 } })
this.props.history.replace({ pathname: "/login", query: { id: 123 } })
this.props.history.push({ pathname: "/login", query: { id: 123 } })
state 传参
通过这个传参方式,可以在history.location.state里面获取到参数。
history.replace({ pathname: "/login", state: { id: 123 } })
history.push({ pathname: "/login", state: { id: 123 } })
this.props.history.replace({ pathname: "/login", state: { id: 123 } })
this.props.history.push({ pathname: "/login", state: { id: 123 } })
十、路由传参的方案总结
1. 动态路由
<Route path="/login/:id" component={Login}></Route>
<NavLink to="/login/123">login</NavLink>
<button
onClick={() => {
history.replace("/login/123")
}}
>
按钮--go-login
</button>
备注:推荐使用,分享链接,参数不会丢失
2. query传参
history.replace({ pathname: "/login", query: { id: 123 } })
history.push({ pathname: "/login", query: { id: 123 } })
备注:参数保存在内存中,分享链接会丢失
3. state传参
history.replace({ pathname: "/login", state: { id: 123 } })
history.push({ pathname: "/login", state: { id: 123 } })
备注:参数保存在内存中,分享链接会丢失
十一、路由拦截
这种做法比较麻烦
<Route
path="/login"
render={() => {
let token = sessionStorage.getItem("TOKEN")
return token ? <Home /> : <Redirect to="/login"></Redirect>
}}
></Route>
使用路由的鉴权组件
import React from "react"
import { Redirect } from "react-router-dom"
const IsAuth = (props) => {
let token = sessionStorage.getItem("TOKEN")
return token ? props.children : <Redirect to="/login"></Redirect>
}
export default IsAuth
<Route
path="/home"
render={() => (
<IsAuth>
<Home />
</IsAuth>
)}
></Route>