• React 路由基础--React路由介绍


    1.React路由介绍

    现代的前端应用大多都是 SPA(单页应用程序)single page application,也就是只有一个 HTML 页面的应用程序。因为它的用户体 验更好、对服务器的压力更小,所以更受欢迎。

    为了有效的使用单个页面来管理原来多页面的功能,前端路由 应运而生。 

    前端路由的功能:让用户从一个视图(页面)导航到另一个视图(页面)

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

    帮助我们实现组件之间的动态切换。

    1.前后端的路由介绍:

    • 后端路由:key:路径;value:function;node;接收一个请求,根据请求路径找到对应的路由,找到之后,会去调用路由中的函数来处理请求,返回响应数据。
    • 前端路由:key:路径;value:component;当浏览器的路径为了在项目中设置的路径,当前的路由组件变为对应的组件。

    2.核心组件

    1.BrowerRouter

    作用:包裹整个应用,一个 React 应用只需要使用一次

    两种常用 Router : HashRouter 和 BrowserRouter

    2.HashRouter

    使用 URL 的哈希值实现(http://localhost:3000/#/first)

    BrowserRouter ( 推荐 )

    使用 H5 的 history.pushState API 实现(http://localhost:3000/first)

    作用 :用于指定导航链接,完成路由跳转

    语法说明: 组件通过to属性指定路由地址,最终会渲染为a链接元素

    4.Routes

    作用 :提供一个路由出口,满足条件的路由组件会渲染到组件内部,定义path和组件的对应关系

    5.Route

    作用 :用于指定导航链接,完成路由匹配

    语法说明: path属性指定匹配的路径地址,element属性指定要渲染的组件

    说明:当url路径为 ‘/about’ 时,会渲染 组件

    2.路由的使用步骤

    1.安装:yarn add react-router-dom

    1. npm install react-router-dom@6
    2. //新版

    2.导入路由的三个核心组件:Router / Routes / Route/Link

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

    3.使用 Router 组件包裹整个应用(重要)

    1. <Router>
    2. <div className="App">
    3. // … 省略页面内容
    4. div>
    5. Router>

    4.用Routes包裹内部Route页面内容

    1. <Routes>
    2. <Route path="/" element>Route>
    3. <Route path="/first" element={<First />}>Route>
    4. Routes>

    5.使用 Link 组件作为导航菜单(路由入口)(Link指定跳转的对应路由组件的路径,to是用来配置路由地址)

     <Link to="/first">页面一Link>
    

    6.使用 Route 组件配置路由规则和要展示的组件(路由出口),在子路由外面用Routes包裹

    1. const First = () => <p>页面一的页面内容p>
    2. // 使用Router组件包裹整个应用
    3. const App = () => (
    4. <Router>
    5. <div>
    6. <h1>React路由基础h1>
    7. {/* 指定路由入口 */}
    8. <Link to="/first">页面一Link>
    9. //路由出口:路由地址对应的组件会在这里进行渲染
    10. <Routes>
    11. <Route path="/" element>Route>
    12. {/* 指定路由出口 */}
    13. //指定路径和组件之间的映射关系。path:路径;element:组件,成对出现
    14. <Route path="/first" element={<First />}>Route>
    15. Routes>
    16. div>
    17. )

    添加一个代码,可以避免警告。

    添加一个 “/” 路径的路由

    <Route path="/" element>Route>
    

    验证:

    1.http://localhost:3000/ ,删除first,显示以下内容。

    2.点击页面一后,显示First页面,显示 ’页面一的内容‘ 。

    总结:

    两种常用的路由模式:BrowserRouter和HashRouter

    BrowserRouter

    声明当前要用是一个非hash的模式的路由

    包裹整个应用

    一个React应用只需要使用一次

    HashRouter,hash模式的路由

    一个有#(HashRouter),一个一带#(BrowserRouter)(推荐

    Link

    指定导航链接,完成路由跳转

    to属性指定路由地址,最终被渲染为a标签

    Routes提供一个路由出口,满足条件的路由组件,会渲染到组件内部
    Route

    用于指定路由组件和路由地址

    path:路由组件对应的路径;element:路由组件;成对出现

    3.常用组件说明

    1. Router 组件:包裹整个应用,一个 React 应用只需要使用一次
    2. 两种常用 Router:HashRouter 和 BrowserRouter
    3. HashRouter:使用 URL 的哈希值实现(localhost:3000/#/first)
    4. (推荐)BrowserRouter:使用 H5 的 history API 实现(localhost:3000/first)
    • Link 组件:用于指定导航链接(a 标签)
      1. // to属性:浏览器地址栏中的pathname(location.pathname)
      2. --点击a标签,就会改变浏览器地址栏中的内容了
      3. <Link to="/first">页面一Link>
    • Route 组件:指定路由展示组件相关信息
      1. // path属性:路由规则
      2. // element:展示的组件
      3. // Route组件写在哪,渲染出来的组件就展示在哪
      4. <Route path="/first" element={<First />}>Route>

    4.路由的执行过程

    1. 点击 Link 组件(a标签),修改了浏览器地址栏中的 url 。
    2. React 路由监听到地址栏 url 的变化。
    3. React 路由内部遍历所有 Route 组件,使用路由规则( path )与 pathname 进行匹配。
    4. 当路由规则(path)能够匹配地址栏中的 pathname 时,就展示该 Route 组件的内容。

    5.编程式导航

    跳转 --- 通过js编程的方式进行页面路由的跳转。

    1.场景:点击登录按钮,登录成功后,通过代码跳转到后台首页,如何实现?

    2.编程式导航:通过 JS 代码来实现页面跳转

    更适合携带参数跳转到另一个页面

    1.history方法 

    使用useNavigate跳转,还有一种方法是this.props.history,但是这种方法有的组件不一定能拿到this.props的值

    3. history 是 React 路由提供的,用于获取浏览器历史记录的相关信息

    4. push(path):跳转到某个页面,参数 path 表示要跳转的路径

    5. go(n): 前进或后退到某个页面,参数 n 表示前进或后退页面数量(比如:-1 表示后退到上一页)

    1. class Login extends Component {
    2. handleLogin = () => {
    3. // ...
    4. this.props.history.push('/home')
    5. }
    6. render() {...省略其他代码}
    7. }

    1.案例说明:

    1.导入路由

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

    2.用Router包裹整个应用

    1. <Router>
    2. <div>
    3. <h1>编程式导航:h1>
    4. div>
    5. Router>

    3.Link创建导航菜单

     <Link to="/login"> 去登录页面Link>
    

    4.配置路由规则

    1. <Route path="/" element>Route>
    2. <Route path="/login" element={<Login />}>Route>
    3. <Route path="/home" element={<Home />}>Route>

    5.用Routes包裹所有的Route

    1. <Routes>
    2. <Route path="/login" element={<Login />}>Route>
    3. ...
    4. Routes>

    6.中途检验:

    1.回到http://localhost:3000/地址,显示

     

     2.点击 去登录页面,显示

    7.给按钮绑定点击事件

    1. handleLogin = () => {
    2. // 使用编程式导航实现路由跳转
    3. // ...省略其他功能代码
    4. this.props.history.push('/home')
    5. }

    报错:

    2.使用useNavigate方法跳转

    执行useNavigate函数会得到一个跳转函数。 

    1. const navigate = useNavigate()
    2. navigate('/home');

    报错:https://reactjs.org/warnings/invalid-hook-call-warning.html

    为避免混淆,其他情况下不支持调用 Hooks:

    🔴 不要在类组件中调用 Hooks。

    🔴 不要调用事件处理程序。

    🔴不要在传递给 useMemo, useReduce ,useEffect 的函数中调用 Hooks

    最后,改类组件,变函数,用useNavigate完成

    1.语法说明:

    1. 导入useNavigate钩子函数
    2. 执行钩子函数得到跳转函数
    3. 执行跳转函数完成跳转
    1. import { useNavigate } from 'react-router-dom'
    2. const Login = props => {
    3. const navigate = useNavigate()
    4. const handleLogin = () => {
    5. navigate('/home')
    6. }
    7. return (
    8. <div>
    9. <p>登录页面:p>
    10. <button onClick={handleLogin}>登录button>
    11. div>
    12. )
    13. }

    2.代码实现:

    1.声明Login小组件

    1. function Login () {
    2. return (
    3. <div>Logindiv>
    4. )
    5. }
    6. export default Login

    2.加入App中

    1. import Login from './Login'
    2. <Route path="login" element={<Login />}>Route>

    3.Login跳到About

    • Login.js导入useNavigate
      import {useNavigate} from 'react-router-dom'
      
    • 执行useNavigate得到一个跳转函数
      1. const navigate = useNavigate()
      2. // 跳转到About页
      3. function goAbout(){
      4. }
    • 调用跳转函数传入目标路径
      1. function goAbout(){
      2. navigate('/about')
      3. }
    • 加replace,以替换的形式跳转,而不是叠加
      navigate('/about',{replace:true})
      

    注意:如果在跳转时不想加历史记录,可以添加额外参数replace为true

    3.完整代码:

    1. //导入react
    2. import React from 'react'
    3. import { createRoot } from 'react-dom/client';
    4. // 导入路由
    5. import { BrowserRouter as Router, Routes, Route, Link, useNavigate } from 'react-router-dom'
    6. const Login = props => {
    7. const navigate = useNavigate()
    8. const handleLogin = () => {
    9. navigate('/home')
    10. }
    11. return (
    12. <div>
    13. <p>登录页面:p>
    14. <button onClick={handleLogin}>登录button>
    15. div>
    16. )}
    17. const Home = props => {
    18. const navigate = useNavigate()
    19. const handleBack = () => {
    20. navigate('/login')
    21. }
    22. return (
    23. <div>
    24. <h2>我是后台首页h2>
    25. {/* 函数里面没有this了 */}
    26. <button onClick={handleBack}>返回登录页面按钮button>
    27. div>
    28. )}
    29. // 使用Router组件包裹整个应用
    30. const App = () => (
    31. <Router>
    32. <div>
    33. <h1>编程式导航:h1>
    34. <Link to="/login"> 去登录页面Link>
    35. <Routes>
    36. <Route path="/" element />
    37. <Route path="/login" element={<Login />} />
    38. <Route path="/home" element={<Home />} />
    39. Routes>
    40. div>
    41. Router>
    42. )
    43. const container = document.getElementById('root');
    44. const root = createRoot(container);
    45. root.render(<App />);

    2.replace:true案例说明:

    1. import { BrowserRouter as Router, Routes, Route, useNavigate } from 'react-router-dom'
    2. function Home () {
    3. // 执行useNavigate函数会得到一个跳转函数
    4. const navigate = useNavigate()
    5. function goAbout () {
    6. //跳转到关于页面,调用跳转函数转入参数(目标路径)
    7. // 如果在跳转时,不想添加历史记录,可以设置第二个参数,传入对象,对象中有replace:true
    8. navigate('/about', { replace: true })
    9. }
    10. return (
    11. <div>
    12. <h2>首页h2>
    13. <button onClick={goAbout}>跳转到关于页面button>
    14. div>
    15. )}
    16. function About () {
    17. return (
    18. <div>
    19. <h2>关于h2>
    20. div>
    21. )}
    22. function App () {
    23. return (
    24. <Router>
    25. <Routes>
    26. <Route path="/" element={<Home />} />
    27. <Route path="/about" element={<About />} />
    28. Routes>
    29. Router>
    30. )}
    31. export default App

    3.也可以更改版本

    npm i react-router-dom@5.0
    

    1.初始代码

    1. // 导入路由
    2. import { BrowserRouter as Router, Route, Link } from 'react-router-dom'
    3. class Login extends React.Component {
    4. handleLogin = () => {
    5. // 使用编程式导航实现路由跳转
    6. // ...省略其他功能代码
    7. this.props.history.push('/home')
    8. }
    9. render() {
    10. return (
    11. <div>
    12. <p>登录页面:p>
    13. <button onClick={this.handleLogin}>登录button>
    14. div>
    15. )
    16. }
    17. }
    18. const Home = () => (
    19. <div>
    20. <h2>我是后台首页h2>
    21. div>
    22. )
    23. // 使用Router组件包裹整个应用
    24. const App = () => (
    25. <Router>
    26. <div>
    27. <h1>编程式导航:h1>
    28. <Link to="/login"> 去登录页面Link>
    29. <Route path="/login" component={Login}>Route>
    30. <Route path="/home" component={Home}>Route>
    31. div>
    32. Router>
    33. )

    2.完整代码

    1. //导入react
    2. import React from 'react'
    3. import ReactDOM from 'react-dom'
    4. // 导入路由
    5. import { BrowserRouter as Router, Route, Link } from 'react-router-dom'
    6. class Login extends React.Component {
    7. handleLogin = () => {
    8. // 跳转到具体的页面
    9. this.props.history.push('/home')
    10. }
    11. render() {
    12. return (
    13. <div>
    14. <p>登录页面:p>
    15. <button onClick={this.handleLogin}>登录button>
    16. div>
    17. )
    18. }
    19. }
    20. const Home = props => {
    21. const handleBack = () => {
    22. //go(-1)返回上一个页面
    23. props.history.go(-1)
    24. }
    25. return (
    26. <div>
    27. <h2>我是后台首页h2>
    28. {/* 函数里面没有this了 */}
    29. <button onClick={handleBack}>返回登录页面按钮button>
    30. div>
    31. )
    32. }
    33. // 使用Router组件包裹整个应用
    34. const App = () => (
    35. <Router>
    36. <div>
    37. <h1>编程式导航:h1>
    38. <Link to="/login"> 去登录页面Link>
    39. <Route path="/login" component={Login} />
    40. <Route path="/home" component={Home} />
    41. div>
    42. Router>
    43. )
    44. ReactDOM.render(<App />, document.getElementById('root'))

    6.组件路由跳转携带参数 

    跳转携带参数

    场景 :有些时候不光需要跳转路由还需要传递参数 

    1. SearchParams传参

    1.使用步骤:

    1.传参

    navigate('/about?id=1', { replace: true })
    

    2.取参

    导入钩子函数

    import {useSearchParams} from 'react-router-dom'
    

    执行钩子函数

    1. // params是一个对象,对象里面有一个get的方法
    2. // 用来获取对应的参数
    3. // 把参数的名称作为get方法的实参传过来
    4. const [params] = useSearchParams()

    把参数的id作为get方法的实参传过来

      const id = params.get('id')
    

    把id渲染出来

    <div>about得到的参数id值为:{id}div>
    

    如果要在id后面拼接name(id&name)

    1. function About () {
    2. const [params] = useSearchParams()
    3. const id = params.get('id')
    4. const name = params.get('name')
    5. return (
    6. <div>about得到的参数id值为:{id}{name}div>
    7. )
    8. }

    在页面搜索

    http://localhost:3000/about?id=1&name='zz'
    

    查看params有什么方法

      console.log(params)
    

    当输入了两个id,以第一个id为主

    http://localhost:3000/about?id=1&name='zz'&id=111
    

    最后结果:id=1

                          

    2.完整代码:

    1. import { BrowserRouter as Router, Routes, Route, useNavigate, useSearchParams } from 'react-router-dom'
    2. function Home () {
    3. const navigate = useNavigate()
    4. function goAbout () {
    5. navigate('/about?name=zz&age=10', { replace: true })
    6. }
    7. return (
    8. <div>
    9. <h2>首页h2>
    10. <button onClick={goAbout}>跳转到关于页面button>
    11. div>
    12. )}
    13. function About () {
    14. console.log(useSearchParams())//0:数组;1.回调函数
    15. const [params] = useSearchParams()
    16. console.log(params.get('name'))//想要拿去哪个参数,就在get里传字符串形式的参数
    17. // 定义变量,进行接收
    18. const name = params.get('name')
    19. return (
    20. <div>
    21. <h2>关于h2>
    22. <h2>{name}h2>
    23. <h2>{params.get('name')}h2>
    24. div>
    25. )}
    26. function App () {
    27. return (
    28. <Router>
    29. <Routes>
    30. <Route path="/" element={<Home />} />
    31. <Route path="/about" element={<About />} />
    32. Routes>
    33. Router>
    34. )}

    2.params传参(path配合:/:id)

    1.实现步骤:

    1.修改

    • 更改goAbout
      navigate('/about/1', { replace: true })
      
    • 在定义路由的位置修改,App.js
       <Route path="/about/:id" element={<About />}>Route>
      

    2.取参

    1. import { useParams } from 'react-router-dom'
    2. function About () {
    3. const params = useParams()
    4. // params为对象
    5. console.log(params)
    6. return (
    7. <div>about得到的参数id值为:{params.id}div>
    8. )
    9. }

    2. 代码解释

    1. import { BrowserRouter as Router, Routes, Route, useNavigate, useParams } from 'react-router-dom'
    2. function Home () {
    3. const navigate = useNavigate()
    4. function goAbout () {
    5. navigate('/about/01', { replace: true })
    6. }
    7. return (
    8. <div>
    9. <h2>首页h2>
    10. <button onClick={goAbout}>跳转到关于页面button>
    11. div>
    12. )
    13. }
    14. function About () {
    15. console.log(useParams())
    16. const params = useParams()
    17. return (
    18. <div>
    19. <h2>关于h2>
    20. <h2>{params.id}h2>-->可以拿到01
    21. div>
    22. )
    23. }
    24. function App () {
    25. return (
    26. <Router>
    27. <Routes>
    28. <Route path="/" element={<Home />} />
    29. <Route path="/about/:id" element={<About />} />
    30. Routes>
    31. Router>
    32. )
    33. }
    34. export default App

    3.id是动态的参数

    1. function Home () {
    2. const navigate = useNavigate()
    3. const [id] = useState(10)
    4. function goAbout () {
    5. navigate('/about/' + id)
    6. }}

    7.默认路由

    • 问题:现在的路由都是点击导航菜单后展示的,如何在进入页面的时候就展示呢?
    • 默认路由:表示进入页面时就会匹配的路由
    • 默认路由path为:/
    <Route path="/" component={Home} />
    

    8.匹配模式

    1.模糊匹配模式

    • 问题:当 Link组件的 to 属性值为 “/login”时,为什么 默认路由 也被匹配成功?
    • 默认情况下,React 路由是模糊匹配模式
    • 模糊匹配规则:只要 pathname 以 path 开头就会匹配成功
    1. <Link to="/login">登录页面Link>
    2. <Route path="/" component={Home} /> 匹配成功

    path:代表Route组件的path属性

    pathname:代表Link组件的to属性(也就是 location.pathname)

    2.精确匹配

    • 问题:默认路由任何情况下都会展示,如何避免这种问题?
    • 给 Route 组件添加 exact 属性,让其变为精确匹配模式
    • 精确匹配:只有当 path 和 pathname 完全匹配时才会展示该路由
    1. // 此时,该组件只能匹配 pathname=“/” 这一种情况
    2. <Route exact path="/" component=... />

    推荐:给默认路由添加 exact 属性。

    9.嵌套路由

    一个路由页面里面,还有路由页面,根据路由路由跳转 。

    对于二级路由的路径,可以不用写 “ /  ”

     Home.js

    1. import React from 'react'
    2. import { Link, Outlet } from 'react-router-dom'
    3. // 类子组件
    4. function Home () {
    5. return (
    6. <div>
    7. <h2>首页h2>
    8. <Link to="news">新闻Link>
    9. <Link to="share">分享Link>
    10. {/* 设置二级路由出口 */}
    11. <Outlet />
    12. div>
    13. )}
    14. // 导出组件
    15. export default Home

    App.js

    1. import Home from './Home'
    2. import News from './News'
    3. import Share from './Share'
    4. import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'
    5. function App () {
    6. return (
    7. <Router>
    8. <Routes>
    9. <Route path="/" element={<Home />} >
    10. {/* 定义嵌套关系,首页中嵌套路由 */}
    11. <Route path="news" element={<News />} />
    12. <Route path="share" element={<Share />} />
    13. Route>
    14. Routes>
    15. Router>
    16. )}
    17. export default App

    1.设置默认二级路由

    将本身的path去除掉,添加属性index 

    1.给默认路由标记index,

    2.修改跳转路径path->删除

     App.js

    <Route index element={<News />} />

    Home.js

    直接跳转到首页,就可以显示新闻页面了

    <Link to="/">新闻Link>

    10.404配置

     写在所有路径的最下面

    场景 :当所有的路径都没有匹配的时候显示

    语法说明: 在各级路由的最后添加 * 号路由作为最后的路由。

    1. import NotFound from './NotFound'
    2. //当所有的路径都没有匹配时,就显示404页面
    3. <Route path="*" element={<NotFound />} >Route>

    11.小案例

    准备两个按钮,点击不同按钮切换不同内容显示。  

     1.创建About.js,Home.js

    1. function Home (){
    2. return(
    3. <div>aboutdiv>
    4. )
    5. }
    6. export default Home

    2.App.js引入这两个组件

    1. import Home from './Home'
    2. import About from './About'

    3.进行路由配置

    import {BrowserRouter,Routes,Route,Link} from 'react-router-dom'
    

    4.点击跳转和路由出口配置

    1. function App () {
    2. return (
    3. <Router>
    4. {/* 点击跳转 */}
    5. // 指定跳转的组件 to用来配置路由地址
    6. <Link to="/">首页Link>
    7. <Link to="/about">关于Link>
    8. {/* 路由出口位置 */}
    9. // 路由对应的组件会在这里进行渲染
    10. <Routes>
    11. // 指定路径和组件的对应关系 path代表路径 element代表组件 成对出现
    12. // path->element
    13. <Route path="/" element={<Home />}>Route>
    14. <Route path="about" element={<About />}>Route>
    15. Routes>
    16. Router>
    17. )
    18. }

    总结

    1. React 路由可以有效的管理多个视图(组件)实现 SPA
    2. Router组件包裹整个应用,只需要使用一次
    3. Link组件是入口,Route组件是出口
    4. 通过 props.history 实现编程式导航
    5. 默认模糊匹配,添加 exact 变精确匹配
    6. React 路由的一切都是组件,可以像思考组件一样思考路由

  • 相关阅读:
    CopyOnWriteArrayList源码分析
    Pytest电商项目实战(上)
    你真的懂单例模式么
    卡尔曼滤波讲解
    SpringCloud-ES学习 第七天
    【JVM】JVM的内存区域划分
    nodejs 不支持 atob、btoa解决方案(Base64加解密、base64与uint8array转换)
    千峰商城-springboot项目搭建-81-订单提交及支付-qrcode生成二维码
    【学习笔记】【DOA子空间算法】7 MUSIC-like 算法
    Python吴恩达深度学习作业19 -- 字符级语言模型
  • 原文地址:https://blog.csdn.net/m0_54088431/article/details/126745582