React路由

97 阅读4分钟

一个路由就是一个映射关系(key:value),key为路由路径, value可能是function/component。

就是对浏览器的地址栏进行监测,当发现地址栏的地址发生变化,会根据地址的路由路径去匹配相对应的组件,并在展示区域展示。

在react项目使用 react-router-dom 来控制路由,这个插件是专门为web网页使用的。

react-router-dom V5

  • 现在最新的版本是 V6
  • 下载指定版本需要指定版本号
  • 在项目中想要使用路由对整个页面的控制,也就是能够监听全局所有的改变路由地址的操作,同时能够根据路由地址变化去渲染不同的组件,这是就需要将整个项目的根组件包裹在路由中
  • 所以一般可以在项目的入口文件中在挂载 App 组件使使用路由再包裹一层
  • 路由模式有两种:BrowserRouter 和 HashRouter
  • 路由匹配模式默认为模糊匹配
// index.js 项目入口文件
import React from 'react';
import ReactDOM from 'react-dom/client';
import { BrowserRouter as Router} from 'react-router-dom' // 这里使用改名引入,这样后期需要更改路由模式时就直接修改这里即可
import App from './App';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <Router>
    <App />
  </Router>
);

react-router-dom插件中的组件

  • <BrowserRouter> <HashRouter>

    • 这两个组件决定了项目的路由模式,使用方式是在项目的入口文件将根组件包裹在挂载到指定容器中
  • <Route>

    • 使用语法:<Route path='想要匹配的路径' component={想要加载的组件}>
    • 当页面路由改变就会跟Route中的path匹配,匹配成功则渲染component绑定的组件
    • 想要加载的组件只需要写引入时定义的变量即可,不需要使用 <> 包裹
    • 而当前的组件称之为路由组件
    • 路由组件的 props 接收到三个固定属性:history、location、match
  • <Link> <NavLink>

    • link 和 NavLink 的使用相同,都可以修改路由地址
    • 语法:<link to='指定一个路由地址'></link> <NavLink to='指定一个路由地址'></NavLink>
    • link 不会根据当前的路由地址,对自己进行一个高亮提示。而 NavLink 却相反
    • NavLink 还可以通过给属性 activeClassName 传入一个class名,这样就可以自定义高亮的样式
    • 以上连接跳转默认是 push 方式跳转,可以添加属性 replace ,可以让当前的路由不被记录
  • <Switch>

    • 用来包裹组件 Route 列表
    • 使用 Switch 包裹的路由列表在匹配的时候会在匹配成功后就终止匹配,后面的路由组件就不会再去匹配
    • 这样可以提高效率,减少计算
  • <Redirect>

    • 重定向路由
    • 语法:<Redirect to="指定一个路由地址" />
    • 用于在路由组件列表的底部使用,当前面的路由组件都没有匹配上时,就跳转到Redirect指定的路由地址
// 举例
<Switch>
    <Route path="/about" component={About}/>
    <Route path="/home" component={Home}/>
    <Redirect to="/about"/>
</Switch>

路由嵌套

  • 在路由组件中继续嵌套路由时,需要注意将所有的父级路由路径写完整,才可以展示完整的路由组件
// 父级路由
<Route path='/home' component={home}>

// 在home的组件中再嵌套路由, 下面是举例在组件中
<NavLink to="/home/new"></NavLink> // 这里 to 的地址一定要把所有父级路由依照嵌套关系写,有多层就写多级

<Route path="/home/new" component={home}> // 这里匹配的 path 也是一样

向路由组件传递参数

  • params 参数传递
    • 路由连接携带参数:<NavLink to="/home/new/18"></NavLink>
    • 注册路由时接收参数:<Route path="/home/new/:id" component={home}>
    • 路由组件中通过:this.peops.match.params 获取参数
  • search 参数传递
    • 路由连接携带参数:<NavLink to="/home/new/?id=18&title=你好"></NavLink>
    • 注册路由时无需接收参数<Route path="/demo/test" component={Test}/>
    • 路由组件中通过:this.props.location.search
    • 备注:获取到的search是urlencoded编码字符串,需要借助querystring插件解析,这个插件脚手架已经帮我们下载好了
// 路由组件中引入 querystring
import qs from 'querystring'

const search = qs.parse(this.props.location.search.slice(1)) 
// 因为 search 参数是一串字符串,且字符串前带有?,所以先截取,再通过 qs 转义为对象
  • state参数
    • 路由链接(携带参数):<Link to={{pathname:'/demo/test',state:{name:'tom',age:18}}}>详情</Link>
    • 注册路由(无需声明,正常注册即可):<Route path="/demo/test" component={Test}/>
    • 接收参数:this.props.location.state
    • 备注:刷新也可以保留住已传递的参数

编程式导航

借助this.prosp.history对象上的API对操作路由跳转、前进、后退

  • this.prosp.history.push('跳转地址', state) 向页面栈添加当前页面记录,再跳转到下一个页面
  • this.prosp.history.replace('跳转地址', state) 页面栈不保留当前页面记录,直接跳转到下一个页面
    • 上面的跳转方式,第二个参数为可选参数,传递的是state参数。其他参数传递编写在地址中
  • this.prosp.history.goBack() 后退
  • this.prosp.history.goForward() 前进
  • this.prosp.history.go(n) n 为正整数时则前进 n 步,n为负整数则后退 n 步

withRouter

  • withRouter可以加工一般组件,让一般组件具备路由组件所特有的API
  • withRouter的返回值是一个新组件
// 在一个组件内 引入
import { withRouter } from 'react-router-dom'

class Header extends Component{}

// 暴露的时候
export default withRouter(Header)

BrowserRouter与HashRouter的区别

  1. 底层原理不一样:
    • BrowserRouter使用的是H5的history API,不兼容IE9及以下版本。
    • HashRouter使用的是URL的哈希值。
  2. path表现形式不一样
    • BrowserRouter的路径中没有#,例如:localhost:3000/demo/test
    • HashRouter的路径包含#,例如:localhost:3000/#/demo/test
  3. 刷新后对路由state参数的影响
    • .BrowserRouter没有任何影响,因为state保存在history对象中。
    • .HashRouter刷新后会导致路由state参数的丢失!!!
  4. 备注:HashRouter可以用于解决一些路径错误相关的问题。