react路由

150 阅读5分钟

本文已参与[新人创作礼]活动,一起开启掘金创作之路

一.路由介绍

现代的前端应用大多都是 SPA(单页应用程序),也就是只有一个 HTML 页面的应用程序。因为它的用户体验更好、对服务器的压力更小,所以更受欢迎。为了有效的使用单个页面来管理原来多页面的功能,前端路由应运而生。前端路由的功能:让用户从一个视图(页面)导航到另一个视图(页面)

  • 前端路由是一套映射规则,在React中,是 URL路径组件 的对应关系
  • 使用 React 路由简单来说就是:配置路径和组件(配对)

二.路由5.X的配置及其与6.X的区别

juejin.cn/post/703070…

三.路由三大对象之-Router

两种常用 Router

HashRouter=====hash

HashRouter:使用 URL 的哈希值实现 /#/page1

#之后的部分就是hash值,它有两个特点:

  1. hash值的变化(地址栏中改了hash值再回车)不会重新发请求。它不是请求路径的一部分。
  2. hash值的变化会触发hashChange事件。

BrowserRouter====history

用 H5 的 history.pushState() API 实现

原理:监听 window 的 popstate 事件来实现的

四.基本使用步骤

1.下包

yarn add react-router-dom@5.2.1

2.导包

import { HashRouter as Router, Route, Link } from 'react-router-dom'

使用Router包裹住整个return,一个项目只有一个Router

3.使用

使用Route指定路由规则(哪个路径显示哪个组件)

import React from 'react'
import {HashRouter as Router, Route, Link} from 'react-router-dom'
import Layout from './Layout'//注意Layout为该路径暴露出的组件
const Func = () => {
  return (
  <Router>
  <div>
    logout
      <Link to='/layout/first'>登录</Link>
      <Route path='/layout' component={Layout}></Route>
</div></Router>)
};
export default Func

五.路由三大对象之-Route

  1. 作用: 决定路由匹配规则

  2. 格式:<Route path="/xx/xx" component={组件}></Route>

匹配规则

名词约定:

  1. path: Route组件中path属性的值

  2. pathname: 指的如下格式

    1. link组件中to的属性值
    2. 地址栏中的地址

模糊匹配规则

  1. 只要pathname以path开头就算匹配成功
  2. 匹配成功就加载对应组件;
  3. 整个匹配过程是逐一匹配,一个匹配成功了,并不会停止匹配

模糊匹配和精确匹配

  1. 默认是模糊匹配的
  2. 补充exact可以设置成精确匹配

六.路由三大对象之-Link

  • 掌握Link和NavLink的区别;

  • 能使用NavLink设置高亮效果;

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

1.Link

Link组件最终会渲染成a标签,用于指定路由导航

  • to属性,将来会渲染成a标签的href属性
  • Link组件无法展示哪个link处于选中的效果

2.NavLink

NavLink组件,一个更特殊的Link组件,可以用用于指定当前导航高亮

格式:<NavLink to="/xxx" activeClassName="active">链接</NavLink>

3.说明:

  • to属性,用于指定地址,会渲染成a标签的href属性
  • activeClassName: 用于指定高亮的类名,默认active。一般不去修改。
  • exact: 精确匹配,表示必须地址栏和to的属性值 精确匹配类名才生效,如果有3个写了一个就会只限制写的那个,若想都限制需要都写
  • switch:将多个路由占位符包住,不管有多少个Route的路由规则匹配成功,都只会渲染第一个匹配的组件
  • '/'是关键字,跟所有路径都相似,若同时跟其他路径使用的话最好配合switch和exact

说多了也没啥用,上事例

image.png

image.png

image.png

image.png

4.重定向和404

404思路:不设置path属性,将404页对应的路由放在switch内部的最后位置

重定向思路:利用from使对应路由直接跳转到to设置的路由中

      <Redirect from='/' to='qq'></Redirect>//重定向
          
      <Route component={Func}></Route>//404
          

建议用Switch包起来,因为404没有路径不包住的话每个页面都会显示

七.编程式导航

  1. 用户点击链接跳转
  2. 写代码跳转-编程式导航
import { useHistory,useLocation  } from 'react-router-dom'
  const  history = useHistory()
  const location=useLocation()
 <li onClick={()=>history.push('/layout/first')}> first</li>

了解:history.replace和push的区别

push:向历史记录中添加一条

replace:在历史记录中用目标记录来替换当前记录

八.声明式导航

 <NavLink to="/layout/second">second</NavLink>
 <Link to='/layout/first'>登录</Link>

九.路由嵌套

配置嵌套路由的时候,需要对路径进行处理,必须要先匹配到父级路由,才能匹配到子路由

image.png

十.综合实例:路由显示左侧菜单

可copy

样式 src\App.css

.app .layout{
  width: 100vw;
  height: 100vh;
  background-color: pink;
  display: flex;
  flex-direction: column;
}
.app .box{
  display: flex;
  flex:1;
}
.app .box .sideBar{
width:200px;
background-color: yellow;
}
.app .box main{
  flex:1;
  background-color: green;
}
.app .box .right{
  background-color: rgb(7, 197, 255);
}

登录 src\views\Router\admin\Layout.js

import React from 'react'
import {
  HashRouter as Router,
  Route,
  Link,
  NavLink,
} from 'react-router-dom'
import First from './First'
import Second from './Second'
import Third from './Third'
import Forth from './Forth'
const Layout = (props) => {
  return (
    <Router>
    <div className="layout">
      <header>
        <Link to="/logout">退出</Link>
      </header>
      <div className="box">
        <div className="sideBar">
          <ul>
            <li onClick={()=>props.history.push('/layout/first')}>
             first
            </li>
            <li>
              <NavLink to="/layout/second">second</NavLink>
            </li>
            <li>
              <NavLink to="/layout/third">third</NavLink>
            </li>
            <li>
              <NavLink to={{
                pathname:'/layout/forth',
                state:{id:1,name:'rose'}
              }}>forth</NavLink>
            </li>
          </ul>
        </div>
        <div className="right">
          <Route path="/layout/first" component={First}></Route>
          <Route path="/layout/second" component={Second}></Route>
          <Route path="/layout/third" component={Third}></Route>
          <Route path="/layout/forth" component={Forth}></Route>
        </div>
      </div>
    </div>
    </Router>
  )
}
export default Layout

登出 src\views\Router\admin\Logout.js

import React from 'react'
import {HashRouter as Router, Route, Link} from 'react-router-dom'
import Layout from './Layout'
const Func = () => {
  return (
  <Router>
  <div>
    ==logout
      <Link to='/layout/first'>登录</Link>
      <Route path='/layout' component={Layout}></Route>
</div></Router>)
};
export default Func

主页 src\App.js

import React from 'react'
import {HashRouter as Router, Route,Redirect } from 'react-router-dom'
import './App.css'
import Layout from './views/Router/admin/Layout'
import Logout from './views/Router/admin/Logout'
class Com extends React.Component {
  render() {
    return (
    <Router>
    <div className="app">
      <Redirect from='/' to='/layout/first'></Redirect>
      <Route path='/layout' component={Layout}></Route>
      <Route path="/logout" component={Logout}></Route>
    </div>
    </Router>
    )
  }
}
export default Com

注意:占位符放在你需要跳转的位置

其他那些二级就没必要发了,随便搞个皮就好

效果图

image.png

十一.路由传参

准备工作

登录页 src\views\Router\admin\Layout.js

<li>
<NavLink to='/layout/forth'>forth</NavLink>
<Route path="/layout/forth" component={Forth}></Route>
 </li>

params传参

登录页 src\views\Router\admin\Layout.js

<li>
 <NavLink to='/layout/forth/123'>forth</NavLink>
 </li>
  <Route path="/layout/forth/:id" component={Forth}></Route>

在src\views\Router\admin\Forth.js 我们打印props可以看到传过来的参数

image.png

可使用{props.match.params.id}调用

注:传多个参数可直接使用/:id/:name即可

query传参

<li>
<NavLink to='/layout/forth?id=321'>forth</NavLink>
 </li>

此时我们在src\views\Router\admin\Forth.js获取到的是"?id=321"

image.png

我们可以封装一个工具函数

  let obj={}  
  const fn=(q)=>{
    // let q=props.location.search
    q=q.slice(1)
    let p=q.split('&')
    for( let k of  p) {
      let item =  k.split('=')
      // console.log(item);
      obj[item[0]]=item[1]
    }
    // return obj
    console.log(obj);
  }
  fn(props.location.search)

效果

image.png

注:传多个参数可参考?id=321&gender=男使用

隐式传参

            <li>
              <NavLink to={{
                pathname:'/layout/forth',
                state:{id:1,name:'rose'}
              }}>forth</NavLink>
            </li>

之前的两种都可以在网址上直接看到,这种则不会

打印props,可以找到数据的获取路径

image.png