最易懂-react18入门系列五

86 阅读6分钟

摘要

本篇主要讲 ReactRouter 路由。

  • 基础使用
  • 嵌套路由
  • 路由模式
  • 路由跳转及传参
  • 声明式导航
  • 编程式导航
  • 404
  • 路由懒加载

什么是前端路由

一个路基path对应一个组件component,当打开浏览器输入一个path的时候,path对应的组件会在页面中进行渲染。

安装

在react项目中执行npm i react-router-dom

demo

以一个需求出发,我们创建一个可以切换登录页和列表页的路由系统。

  • /login:登录页

  • /list:列表页

分2步:

  1. 路由的配置,path 是路径,element是我们要渲染的UI,可以是组件 ,也可以是jsx,也就是一段div dom片段。都是可以的。

  2. 根组件里做路由绑定。

src/index.js

我们把路由配置先不抽离,直接写在index.js里,然后element我们先写个div简单演示,后边再优化。

import React from 'react'
import ReactDOM from 'react-dom/client'
import{createBrowserRouter,RouterProvider} from 'react-router-dom'
import './index.css'

// 1.路由配置
const router= createBrowserRouter([
		{
			path:'/',
			element:<div>我是登录页</div>//<Login/>
		},
		{
			path:'/list',
			element:<div>我是列表页</div>//<List/>
		},
	])

ReactDOM.createRoot(document.getElementById('root')).render(
	<React.StrictMode>
		{/*2.路由绑定*/}
		<RouterProvider router={router}/>
	</React.StrictMode>
)

demo优化

改成日常项目中开发的常见形式。

路由配置从index.js里抽出。 element配置的UI改成组件。

路由导航的跳转

分两种:

  1. 声明式导航

  2. 编程式导航

声明式导航

是指通过在模板中通过组件描述出要跳转到哪里去。比如后台管理系统的左侧菜单通常使用这个种方式进行。

<Link to="/list">列表</Link>

Link:通过给组件to属性赋值上path页面路径来实现跳转,组件会被渲染成浏览器支持的a链接。

编程式导航

是指通过useNavigate 钩子得到导航的方法,然后通过调用方法以命令的形式进行路由跳转。比如在做完某个操作后执行跳转,可以选择这种方式,更加的灵活。

登录页,点击按钮跳转到列表页:

import {useNavigate} form 'react-router-dom'

const Login=()=>{
	const navigate = useNavigate()

	return(
		<div>
			我是登录页
			<button onClick={()=>navigate('/list')}>跳转到列表页</button>
		</div>
	)
}

useNavigate:通过传入path路由地址参数实现跳转。

路由导航的跳转时传参

方式一:

问号传参,也叫searchParams传参。参数作为查询参数。

传入点:

navigate('/list?id=12&name=Macrolam')

接收参数:

使用的是 useSearchParams 钩子函数,调用后解构出params对象,然后通过其下边的get方法来获取指定key的参数值。

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

const List =()=>{
	const [params] = useSearchParams()

	const id = params.get('id')
	const name = params.get('name')

	return <div>我是列表页:{id} {name}</div>
}

export default List

方式二:

斜杠传参,也叫params传参。参数作为路径的一个部分,地址看起来更美观规整些。

传入点:

navigate('/list/12/Macrolam')

同时需要把路由注册地址位置上写上占位,否则找不到。

// ...
const router = createBrowserRouter([
	{
		path:'/list/:id/:name',
		element:<List/>
	}
])

//...

接收参数:

使用的是 useParams 钩子函数,调用后返回params对象,然后点语法读取到对应的参数key值。

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

const List =()=>{
	const params = useParams()

	const id = params.id
	const name = params.name

	return <div>我是列表页:{id} {name}</div>
}

export default List

嵌套路由

在一个一级路由里又嵌套了其他路由,这种关系叫嵌套路由。内部的叫二级路由,当然还可以继续向下嵌套。

场景于:后台管理系统中。

Layout[一级] = Menu + MainUI[二级]

实现步骤

  1. 使用 children 属性配置 路由嵌套关系

  2. 使用 组件作为二级路由渲染的出口位置

案例

左侧是菜单项,右侧是对应的页面。

路由文件:

const router = createBrowserRouter([

	{
		path:'/',
		element:<Layout/>,
		children:[
			{
				path:'board',
				element:<Board/>
			},
			{
				path:'user',
				element:<User/>
			},
		]
	},
	{
		path:'/login',
		element:<Login/>
	},
])

一级路由分发页:layout.jsx

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

const Layout =()=>{
	

	return (
		<div>
			{/*Menu*/}
			<Link to="/">着陆面板</Link>
			<Link to="/user">用户管理</Link>

			{/*MainUI 二级路由出口*/}
			<Outlet/>
		</div>
	)
}

export default Layout

默认二级路由

就是当访问一个一级路由时,里面的二级路由也能默认选中一条进行渲染。

实现: 只需要在路由配置文件里,二级路由的位置去掉path,设置index属性为true。

比如:我们访问首页时候,默认给我们展示面板组件。

//...
import Layout form '../page/Layout'

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

const router = createBrowserRouter([
	{
		path:'/',
		element:<Layout/>,
		children:[
			{
				// path:'board',//del 删除不要
				index:true,//add 新增一条此属性
				element:<Board/>
			},
			{
				path:'user',
				element:<User/>
			},
		]
	},
])

Vue也有类似的需求实现,vue里是把二级路由的path 置空。 这里是设置index=true。

404路由配置

当用户使用系统时,在地址栏输入的地址到我们的路由表里匹配不到时,可以使用404页面作为一个兜底渲染,提示用户当前路径下页面不存在。属于提升用户体验的。

404 的实现:

  1. 准备一个 NotFound 组件

  2. 在路由表数组的末尾,以 * 号 作为 路由path配置路由

const NotFound = ()=>{
	return <div> 404 请访问的页面不存在,点击返回首页...</div>
}
//...
import NotFound form '../page/NotFound'

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

const router = createBrowserRouter([

	{
		path:'/',
		element:<Layout/>,
		children:[
			{
				path:'board',
				element:<Board/>
			},
			{
				path:'user',
				element:<User/>
			},
		]
	},
	{
		path:'/login',
		element:<Login/>
	},
	//...
	// 一定放到最底部
	{
		path:'*',
		element:<NotFound/>
	}

])

路由模式

和vue里一样有两种:

  1. history: 由 createBrowserRouter 函数创建

  2. hash: 由 createHashRouter 函数创建

切换路由模式,只需要切换一个API即可,其他都不用动。至于选择使用哪种模式,主要看下后台是否能配合。

路由模式url表现底层原理是否需要后台配合
historyurl/loginhistory对象 + pushState事件需要
hashurl/#/login监听 hashChange 事件不需要

hash 的路由模式:

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

const router = createHashRouter([

	{
		path:'/login',
		element:<Login/>
	},
	//...
	// 一定放到最底部
	{
		path:'*',
		element:<NotFound/>
	}

])

地址栏默认着陆页:http://localhost:8090/#/ 会多了一段 /#/

登录页:http://localhost:8090/#/login

路由懒加载

首次访问时 ,只加载需要的js。不要全部页面js资源都加载上来。 而是用哪个路由,加载哪个路由下js资源。

目的:优化首次打开时间。

实现

  1. 把路由修改为由 React 提供的lazy 函数进行动态导入

  2. 使用 React 内置的 Suspense 组件 包裹路由中的 element 选项对应的组件

router.js

借助 lazy 函数改导入语句:

//...
import { lazy,Suspense } from 'react'

//1.lazy函数导入
const Home = lazy(() => import('@/pages/Home'))

const router = createBrowserRouter([

	{
		path: "/",
		element:<Layout/>,
		children:[
			{
				index:true,
				element:<Suspense fallback={'加载中'}><Home/></Suspense>//2.Suspense 组件 包裹
			}
		]
	}
])

其中 Suspense 标签身上的 fallback 属性 是配置,异步组件没加载上来之前显示的内容。