1、路由方式

React-Router 中的 3 个核心角色:

  • 路由器,比如 BrowserRouter 和 HashRouter
  • 路由,比如 Route 和 Switch
  • 导航,比如 Link、NavLink、Redirect

路由主要分为两种方式,一种是 history 模式,另一种是 Hash 模式;

2、React-Router 基本构成

2.1 history,location,match

  • history 对象:history对象保存改变路由方法 push ,replace,和监听路由方法 listen 等。
  • location 对象:可以理解为当前状态下的路由信息,包括 pathname ,state 等。
  • match 对象:这个用来证明当前路由的匹配信息的对象。存放当前路由path 等信息。

2.2 exact

Route 可以加上 exact ,来进行精确匹配,精确匹配原则,pathname 必须和 Route 的 path 完全匹配,才能展示该路由信息。

2.3 使用react-router-config

  1. const RouteList = [
  2. {
  3. name: '首页',
  4. path: '/router/home',
  5. exact:true,
  6. component:Home
  7. },
  8. {
  9. name: '列表页',
  10. path: '/router/list',
  11. render:()=><List />
  12. },
  13. {
  14. name: '详情页',
  15. path: '/router/detail',
  16. component:detail
  17. },
  18. {
  19. name: '我的',
  20. path:'/router/person',
  21. component:personal
  22. }
  23. ]
  24. function Index(){
  25. return <div>
  26. <Meuns/>
  27. { renderRoutes(RouteList) }
  28. </div>
  29. }

2.4 Switch

Switch 作用是先通过匹配选出一个正确路由 Route 进行渲染。

  1. <Switch>
  2. <Route path='/home' component={Home} />
  3. <Route path='/list' component={List} />
  4. <Route path='/my' component={My} />
  5. </Switch>

2.5 Redirect

Redirect 可以在路由不匹配情况下跳转指定某一路由。

  1. <Switch>
  2. <Route path='/router/home' component={Home} />
  3. <Route path='/router/list' component={List} />
  4. <Route path='/router/my' component={My} />
  5. <Redirect from={'/router/*'} to={'/router/home' } />
  6. </Switch>

3、路由使用方式

3.1 路由组件 props

被 Route 包裹的路由组件 props 中会默认混入 history 等信息;

  1. class Home extends React.Component{
  2. render(){
  3. return <div>
  4. <Children {...this.props} />
  5. </div>
  6. }
  7. }

3.2 withRouter

对于距离路由组件比较远的深层次组件,通常可以用 react-router 提供的 withRouter 高阶组件方式获取 histroy ,loaction 等信息。

  1. import { withRouter } from 'react-router-dom'
  2. @withRouter
  3. class Home extends React.Component{
  4. componentDidMount(){
  5. console.log(this.props.history)
  6. }
  7. render(){
  8. return <div>
  9. { /* ....*/ }
  10. </div>
  11. }
  12. }

3.3 useHistory 和 useLocation

对于函数组件,可以用 React-router 提供的自定义 hooks 中的 useHistory 获取 history 对象,用 useLocation 获取 location 对象。

  1. import { useHistory ,useLocation } from 'react-router-dom'
  2. function Home(){
  3. const history = useHistory() /* 获取history信息 */
  4. const useLocation = useLocation() /* 获取location信息 */
  5. }

4、使用技巧

4.1 路由跳转

路由跳转有声明式路由函数式路由两种。

  • 声明式: ,利用 react-router-dom 里面的 Link 或者 NavLink 。
  • 函数式:histor.push(‘/home’) 。

4.2 参数传递

url拼接

  1. const name = 'alien'
  2. const mes = 'let us learn React!'
  3. history.push(`/home?name=${name}&mes=${mes}`)

state路由状态

  1. const name = 'alien'
  2. const mes = 'let us learn React!'
  3. history.push({
  4. pathname:'/home',
  5. state:{
  6. name,
  7. mes
  8. }
  9. })
  10. // 获取
  11. const {state = {}} = this.prop.location
  12. const { name , mes } = state

动态路径参数路由

  1. // 参数做路径
  2. <Route path="/post/:id" />
  3. // 跳转
  4. history.push('/post/'+id) // id为动态的文章id

5、路由拓展

5.1 嵌套路由

嵌套路由子路由一定要跟随父路由。比如父路由是 /home ,那么子路由的形式就是 /home/xxx ,否则路由页面将展示不出来。

  1. /* 第二层嵌套路由 */
  2. function Home(){
  3. return <div>
  4. <Route path='/home/test' component={Test} />
  5. <Route path='/home/test1' component={Test1} />
  6. </div>
  7. }
  8. /* 第一层父级路由 */
  9. function Index(){
  10. return <Switch>
  11. <Route path="/home" component={Home} />
  12. <Route path="/list" component={List} />
  13. <Route path="/my" component={My} />
  14. </Switch>
  15. }

5.2 自定义路由

  1. // 定义组件
  2. function CustomRouter(props){
  3. const permissionList = useContext(permissionContext) /* 获取权限列表 */
  4. const haspermission = matchPermission(permissionList,props.path) /* 检查是否具有权限 */
  5. return haspermission ? <Route {...props} /> : <Redirect to="/noPermission" />
  6. }
  7. // 使用
  8. <CustomRouter path='/list' component={List} />

6、实践

第一步:根组件注入权限

  1. function getRootPermission(){
  2. return new Promise((resolve)=>{
  3. resolve({
  4. code:200, /* 数据模拟只有编写文档,和编写标签模块有权限,文档列表没有权限 */
  5. data:[ '/config/index' , '/config/writeTag' ]
  6. })
  7. })
  8. }
  9. /* 路由根部组件 */
  10. const Permission = React.createContext([])
  11. export default function Index(){
  12. const [ rootPermission , setRootPermission ] = React.useState([])
  13. React.useEffect(()=>{
  14. /* 获取权限列表 */
  15. getRootPermission().then(res=>{
  16. const { code , data } = res
  17. code === 200 && setRootPermission(data)
  18. })
  19. },[])
  20. return <Permission.Provider value={rootPermission} >
  21. <RootRouter/>
  22. </Permission.Provider>
  23. }

第二部:编写权限路由

  1. export function PermissionRouter(props){
  2. const permissionList = useContext(Permission) /* 消费权限列表 */
  3. const isMatch = permissionList.indexOf(props.path) >= 0 /* 判断当前页面是否有权限 */
  4. return isMatch ? <Route {...props} /> : <Redirect to={'/config/NoPermission'} />
  5. }

第三部:注册权限路由和无权限跳转页面

  1. <Switch>
  2. <PermissionRouter path={'/config/index'} component={WriteDoc} />
  3. <PermissionRouter path={'/config/docList'} component={DocList} />
  4. <PermissionRouter path={'/config/writeTag'} component={WriteTag} />
  5. <PermissionRouter path={'/config/tagList'} component={TagList} />
  6. <Route path={'/config/NoPermission'} component={NoPermission} />
  7. </Switch>