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

npm install react-router-dom@6
//新版

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

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

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


  
// … 省略页面内容

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

 
    
    }>
  

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

 页面一

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

const First = () => 

页面一的页面内容

// 使用Router组件包裹整个应用 const App = () => (

React路由基础

{/* 指定路由入口 */} 页面一 //路由出口:路由地址对应的组件会在这里进行渲染 {/* 指定路由出口 */} //指定路径和组件之间的映射关系。path:路径;element:组件,成对出现 }>
)

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

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


验证:

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

React 路由基础--React路由介绍_第1张图片

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

React 路由基础--React路由介绍_第2张图片

总结:

两种常用的路由模式: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 标签)
    // to属性:浏览器地址栏中的pathname(location.pathname)
    --点击a标签,就会改变浏览器地址栏中的内容了
    
    页面一
    
  • Route 组件:指定路由展示组件相关信息
    // path属性:路由规则
    // element:展示的组件
    // Route组件写在哪,渲染出来的组件就展示在哪 
    
    }>
    

4.路由的执行过程

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

React 路由基础--React路由介绍_第3张图片

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 表示后退到上一页)

class Login extends Component {
  handleLogin = () => {
   // ...
   this.props.history.push('/home')
  }
 render() {...省略其他代码} 
}

1.案例说明:

1.导入路由

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

2.用Router包裹整个应用


    

编程式导航:

3.Link创建导航菜单

  去登录页面

4.配置路由规则

 
 }>
 }>

5.用Routes包裹所有的Route

 
        }>
        ...
 

6.中途检验:

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

 React 路由基础--React路由介绍_第4张图片

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

React 路由基础--React路由介绍_第5张图片

7.给按钮绑定点击事件

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

报错:

2.使用useNavigate方法跳转

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

 const navigate = useNavigate()
    navigate('/home');

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

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

不要在类组件中调用 Hooks。

不要调用事件处理程序。

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

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

1.语法说明:

  1. 导入useNavigate钩子函数
  2. 执行钩子函数得到跳转函数
  3. 执行跳转函数完成跳转
import { useNavigate } from 'react-router-dom'

const Login = props => {
  const navigate = useNavigate()
  const handleLogin = () => {
    navigate('/home')
  }
  return (
    

登录页面:

) }

2.代码实现:

1.声明Login小组件

function Login () {
  return (
    
Login
) } export default Login

2.加入App中

import Login from './Login'

}>

3.Login跳到About

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

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

3.完整代码:

//导入react
import React from 'react'
import { createRoot } from 'react-dom/client';

// 导入路由
import { BrowserRouter as Router, Routes, Route, Link, useNavigate } from 'react-router-dom'

const Login = props => {
  const navigate = useNavigate()
  const handleLogin = () => {
    navigate('/home')
  }
  return (
    

登录页面:

)} const Home = props => { const navigate = useNavigate() const handleBack = () => { navigate('/login') } return (

我是后台首页

{/* 函数里面没有this了 */}
)} // 使用Router组件包裹整个应用 const App = () => (

编程式导航:

去登录页面 } /> } />
) const container = document.getElementById('root'); const root = createRoot(container); root.render();

2.replace:true案例说明:

import { BrowserRouter as Router, Routes, Route, useNavigate } from 'react-router-dom'
function Home () {
  // 执行useNavigate函数会得到一个跳转函数
  const navigate = useNavigate()
  function goAbout () {
    //跳转到关于页面,调用跳转函数转入参数(目标路径)
    // 如果在跳转时,不想添加历史记录,可以设置第二个参数,传入对象,对象中有replace:true
    navigate('/about', { replace: true })
  }
  return (
    

首页

)} function About () { return (

关于

)} function App () { return ( } /> } /> )} export default App

3.也可以更改版本

npm i [email protected]

1.初始代码

// 导入路由
import { BrowserRouter as Router, Route, Link } from 'react-router-dom'

class Login extends React.Component {
   handleLogin = () => {
  // 使用编程式导航实现路由跳转
  // ...省略其他功能代码

       this.props.history.push('/home')
   }
  render() {
    return (
      

登录页面:

) } } const Home = () => (

我是后台首页

) // 使用Router组件包裹整个应用 const App = () => (

编程式导航:

去登录页面
)

2.完整代码

//导入react
import React from 'react'
import ReactDOM from 'react-dom'
// 导入路由
import { BrowserRouter as Router, Route, Link } from 'react-router-dom'

class Login extends React.Component {
  handleLogin = () => {
    // 跳转到具体的页面
    this.props.history.push('/home')
  }
  render() {
    return (
      

登录页面:

) } } const Home = props => { const handleBack = () => { //go(-1)返回上一个页面 props.history.go(-1) } return (

我是后台首页

{/* 函数里面没有this了 */}
) } // 使用Router组件包裹整个应用 const App = () => (

编程式导航:

去登录页面
) ReactDOM.render(, document.getElementById('root'))

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

跳转携带参数

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

1. SearchParams传参

1.使用步骤:

1.传参

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

2.取参

导入钩子函数

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

执行钩子函数

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

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

  const id = params.get('id')

把id渲染出来

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

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

function About () {
  const [params] = useSearchParams()
  const id = params.get('id')
  const name = params.get('name')

  return (
    
about得到的参数id值为:{id}{name}
) }

在页面搜索

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

React 路由基础--React路由介绍_第6张图片                      React 路由基础--React路由介绍_第7张图片

2.完整代码:

import { BrowserRouter as Router, Routes, Route, useNavigate, useSearchParams } from 'react-router-dom'
function Home () {
  const navigate = useNavigate()
  function goAbout () {
    navigate('/about?name=zz&age=10', { replace: true })
  }
  return (
    

首页

)} function About () { console.log(useSearchParams())//0:数组;1.回调函数 const [params] = useSearchParams() console.log(params.get('name'))//想要拿去哪个参数,就在get里传字符串形式的参数 // 定义变量,进行接收 const name = params.get('name') return (

关于

{name}

{params.get('name')}

)} function App () { return ( } /> } /> )}

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

1.实现步骤:

1.修改

  • 更改goAbout
    navigate('/about/1', { replace: true })
    
  • 在定义路由的位置修改,App.js
     }>
    

2.取参

import { useParams } from 'react-router-dom'
function About () {
  const params = useParams()
  // params为对象
    console.log(params)

  return (
    
about得到的参数id值为:{params.id}
) }

2. 代码解释

import { BrowserRouter as Router, Routes, Route, useNavigate, useParams } from 'react-router-dom'
function Home () {
  const navigate = useNavigate()
  function goAbout () {
    navigate('/about/01', { replace: true })
  }
  return (
    

首页

) } function About () { console.log(useParams()) const params = useParams() return (

关于

{params.id}

-->可以拿到01
) } function App () { return ( } /> } /> ) } export default App

3.id是动态的参数

function Home () {
  const navigate = useNavigate()
  const [id] = useState(10)
  function goAbout () {
    navigate('/about/' + id)
}}

7.默认路由

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

8.匹配模式

1.模糊匹配模式

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

path:代表Route组件的path属性

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

React 路由基础--React路由介绍_第8张图片

2.精确匹配

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

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

9.嵌套路由

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

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

 Home.js

import React from 'react'
import { Link, Outlet } from 'react-router-dom'
// 类子组件
function Home () {
  return (
    

首页

新闻 分享 {/* 设置二级路由出口 */}
)} // 导出组件 export default Home

App.js

import Home from './Home'
import News from './News'
import Share from './Share'
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'
function App () {
  return (
    
      
        } >
          {/* 定义嵌套关系,首页中嵌套路由 */}
          } />
          } />
        
      
    
)}
export default App

1.设置默认二级路由

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

1.给默认路由标记index,

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

 App.js

} />

Home.js

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

新闻

10.404配置

 写在所有路径的最下面

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

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

import NotFound from './NotFound'
//当所有的路径都没有匹配时,就显示404页面
} >

11.小案例

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

React 路由基础--React路由介绍_第9张图片

 1.创建About.js,Home.js

function Home (){
  return(
    
about
) } export default Home

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

import Home from './Home'
import About from './About'

3.进行路由配置

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

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

function App () {
  return (
    
      {/* 点击跳转 */}
      // 指定跳转的组件 to用来配置路由地址
      首页
      关于
             {/* 路由出口位置 */}
        // 路由对应的组件会在这里进行渲染
      
// 指定路径和组件的对应关系  path代表路径  element代表组件 成对出现
        // path->element
        }>
        }>
      
    
  )
}

总结

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

你可能感兴趣的:(React学习,react.js,前端,javascript,前端框架,ecmascript)