React 官方并没有提供对应的路由插件,因此,我们需要下载第三方的路由插件 —— React Router DOM。
React Router 在 2021 年 11 月份的时候更新 v6 的版本。本次课就主要讲解V6版本
在项目根目录中,通过以下命令
yarn add react-router-dom
1)首先在react项目的入口文件index.js文件中,使用将包裹起来
- import {BrowserRouter} from 'react-router-dom'
-
- const root = ReactDOM.createRoot(document.getElementById('root'));
- root.render(
- <BrowserRouter>
- <App />
- BrowserRouter>
- );
BrowserRouter:包裹这个应用,一个React应用只需使用一次
在 React Router 中提供了两种路由模式:hash 和 history。
对应的的路由组件分别是:
HashRouter:hash 模式的路由
BrowserRouter:history 模式的路由
实际使用时,任选其中一个模式引入即可
2)其次,在App.js文件中,使用设置路由出口,使用指定导航链接
- import React from 'react'
- import {Routes,Route} from 'react-router-dom'
- import Login from './pages/Login'
- import Register from './pages/Register'
- import Home from './pages/Home'
- export default function App() {
- return (
- <Routes>
- <Route path='/login' element={<Login/>}>Route>
- <Route path='/register' element={<Register/>}>Route>
- <Route path='/' element={<Home/>}>Route>
- Routes>
- )
- }
核心组件作用说明
Routes:提供一个路由出口,满足条件的路由组件会渲染到组件内部
Route: 用于指定导航链接,完成路由跳转
path:path属性指定匹配的路径地址
element element属性指定要渲染的组件
React Router 中,路由的跳转分为两种方式:
标签(组件)跳转
JS(API)跳转
- import React from 'react'
- import {Link} from 'react-router-dom'
- export default function Login() {
- return (
- <div>
- <h1>用户登录h1>
- <Link to="/register">没有账号,去注册Link>
- div>
- )
- }
实现步骤
导入useNavigate钩子函数
import {useNavigate} from 'react-router-dom'
执行钩子函数得到跳转函数
let navigate=useNavigate();
执行跳转函数完成跳转
- import React from 'react'
- import {useNavigate} from 'react-router-dom'
-
- export default function Register() {
- const navigate=useNavigate()
- const register=(e)=>{
- e.preventDefault()
- navigate('/login')
- }
- return (
- <div>
- <h1>用户注册h1>
- <a href="#" onClick={(e)=>{register(e)}}>已注册,去登录a>
- div>
- )
- }
注意
如果在跳转时不想加历史记录,可以添加额外参数replace为true
- const register=(e)=>{
- e.preventDefault()
- navigate('/login',{replace:true})
- }
实现步骤
定义嵌套路由声明
- <Routes>
- <Route path='/login' element={<Login/>}>Route>
- <Route path='/register' element={<Register/>}>Route>
- <Route path='/' element={<Home/>}>
- <Route path='category' element={<Category/>}>Route>
- <Route path='goods' element={<Goods/>}>Route>
- Route>
- Routes>
设置二级路由出口
- export default function Home() {
- return (
- <>
- <aside>
- <ul>
- <li><NavLink to="/categroy">分类管理NavLink>li>
- <li><NavLink to="/goods">商品管理NavLink>li>
- ul>
- aside>
- <section>
- {/* 二级路由出口 */}
- <Outlet>Outlet>
- section>
- >
- )
- }
- <Routes>
- <Route path='/login' element={<Login/>}>Route>
- <Route path='/register' element={<Register/>}>Route>
- <Route path='/' element={<Home/>}>
- {/*默认二级路由,添加index属性,删除掉path属性*/}
- <Route index element={<Main/>}>Route>
- <Route path='category' element={<Category/>}>Route>
- <Route path='goods' element={<Goods/>}>Route>
- Route>
- Routes>
应用场景:当所有的路径都没有匹配的时候显示
语法说明:在各级路由的最后添加*号路由作为兜底
- <Routes>
- <Route path='/login' element={<Login/>}>Route>
- <Route path='/register' element={<Register/>}>Route>
- <Route path='/' element={<Home/>}>
- {/*默认二级路由,添加index属性,删除掉path属性*/}
- <Route index element={<Main/>}>Route>
- <Route path='category' element={<Category/>}>Route>
- <Route path='goods' element={<Goods/>}>Route>
- Route>
- {/*当所有路径都没有匹配时渲染此路由*/}
- <Route path='*' element={<NotFound/>}>Route>
- Routes>
BrowserRouter模式部署在Nginx服务器上出现404问题的解决办法
在index.js的上添加basename属性,比如
- <BrowserRouter basename='/crem'>
- <App>App>
- BrowserRouter>
在package.json中添加"homepage": "."
- {
- "homepage": "."
- }
在终端上执行打包命令
yarn build
打包后会产生一个build文件夹,然后将该文件改名为crem,
上传文件的linux服务器的/opt目录下
在/etc/nginx/conf.d/default.conf下添加如下配置
- location /crem {
- alias /opt/crem;
- index index.html;
- }
进入shell中执行如下命令
- ps aux|grep nginx #查看nginx进程
- killall -9 nginx #杀死nginx进程
- /usr/sbin/nginx #启动nginx服务器
修改/etc/nginx/conf.d/default.conf文件,添加如下配置即可
- location /crem {
- alias /opt/crem;
- index index.html;
- try_files $uri /crem/index.html;
- }
实现步骤
传参
- import {useNavigate} from 'react-router-dom'
- export default function CategroyList() {
- let navigate=useNavigate();
- return (
- <div>
- <h2>CategroyListh2>
- <button onClick={()=>{navigate('/categroyDetail?id=12')}}>详情button>
- div>
- )
- }
获取参数
- import {useSearchParams} from 'react-router-dom'
-
- export default function CategoryDetail() {
- let [params]=useSearchParams()
- return (
- <div>
- <h2>CategroyDetailh2>
- <div>
- ID:{params.get('id')}
- div>
- div>
- )
- }
实现步骤
路由设置
- <BrowserRouter>
- <Routes>
- <Route path='/home' element={<Layout/>}>
- <Route path='categroy-detail/:id' element={<CategoryDetail/>}>Route>
- Route>
- Routes>
- BrowserRouter>
传参
- import {useNavigate} from 'react-router-dom'
- export default function CategroyList() {
- let navigate=useNavigate();
- return (
- <div>
- <h2>CategroyListh2>
- <button onClick={()=>{navigate('/home/categroy-detail/13')}}>详情button>
- div>
- )
- }
获取参数
- import React from 'react'
- import {useParams} from 'react-router-dom'
-
- export default function CategoryDetail() {
- let params=useParams()
- return (
- <div>
- <h2>CategroyDetailh2>
- <div>
- ID:{params.id}
- div>
- div>
- )
- }
实现步骤
在项目根目录创建router文件夹,并在该目录下创建index.jsx
在router/index.jsx编写路由配置项
- import Login from '../pages/Login'
- import Register from '../pages/Register'
- import Home from '../pages/Home'
- import CategoryList from '../pages/Category'
- import CategoryDetail from '../pages/Category/Detail'
- import GoodsList from '../pages/Goods'
- import Main from '../pages/Home/Main'
- export default [
- {
- path:'/login',
- element:<Login/>
- },
- {
- path:'/register',
- element:<Register/>
- },
- {
- path:'/',
- element:<Home/>,
- children:[
- {
- index:true,
- element:<Main/>
- },
- {
- path:'/categoryList',
- element:<CategoryList/>
- },
- {
- path:'/categoryDetail/:id',
- element:<CategoryDetail/>
- },
- {
- path:'/goodsList',
- element:<GoodsList/>
- }
- ]
- }
- ]
在App.jsx中通过useRoutes钩子函数来进行集中式配置
- import {useRoutes} from 'react-router-dom'
- import router from './router/index'
- function App() {
- return useRoutes(router)
- }
- export default App;
在项目根目录下的index.js中使用包裹
- root.render(
- <BrowserRouter>
- <App/>
- BrowserRouter>
- )
使用lazy(()=>import('xxx'))方式导入组件
- import {lazy} from 'react'
- const Login=lazy(()=>import('../pages/Login'))
- const Register=lazy(()=>import('../pages/Register'))
- const Home=lazy(()=>import('../pages/Home'))
- const CategoryList=lazy(()=>import('../pages/Category'))
- const CategoryDetail=lazy(()=>import('../pages/Category/Detail'))
- const GoodsList=lazy(()=>import('../pages/Goods'))
- const Main=lazy(()=>import('../pages/Home/Main'))
- export default [
- {
- path:'/login',
- element:<Login/>
- },
- {
- path:'/register',
- element:<Register/>
- },
- {
- path:'/',
- element:<Home/>,
- children:[
- {
- index:true,
- element:<Main/>
- },
- {
- path:'/categoryList',
- element:<CategoryList/>
- },
- {
- path:'/categoryDetail/:id',
- element:<CategoryDetail/>
- },
- {
- path:'/goodsList',
- element:<GoodsList/>
- }
- ]
- }
- ]
通过 React 中提供了 组件,来实现路由的懒加载。
- import {Suspense} from 'react'
- function App() {
- return(
- <Suspense fallback={<>loading>}>
- {useRoutes(router)}
- Suspense>
- )
- }
组件身上,必须设置一个 fallback 属性,属性值可以是一个 HTML 标签,也可以是一个自定义的组件。用于当路由组件还未加载出来前的提示。
配置完路由懒加载后出现当进行路由跳转时,出现闪屏现象,要向解决这个问题可以使用 react-loadable插件进行解决
先下载react-loadable依赖包
yarn add react-loadable
建立一个loadable.js,放在src/utils/loadable.js
- import Loadable from 'react-loadable';
- export default function withLoadable(comp) {
- return Loadable({
- //懒加载组件页面
- loader: comp,
- loading: () => null,
- delay: "",
- })
- }
修改router/index.js
- import loadable from '../utils/loadable'
- const Login=loadable(()=>import('../pages/Login'))
- const Register=loadable(()=>import('../pages/Register'))
- const Home=loadable(()=>import('../pages/Home'))
- const CategoryList=loadable(()=>import('../pages/Category'))
- const CategoryDetail=loadable(()=>import('../pages/Category/Detail'))
- const GoodsList=loadable(()=>import('../pages/Goods'))
- const Main=loadable(()=>import('../pages/Home/Main'))
- export default [
- {
- path:'/login',
- element:<Login/>
- },
- {
- path:'/register',
- element:<Register/>
- },
- {
- path:'/',
- element:<Home/>,
- children:[
- {
- index:true,
- element:<Main/>
- },
- {
- path:'/categoryList',
- element:<CategoryList/>
- },
- {
- path:'/categoryDetail/:id',
- element:<CategoryDetail/>
- },
- {
- path:'/goodsList',
- element:<GoodsList/>
- }
- ]
- }
- ]