当前位置: 首页 > article >正文

Redux (八) 路由React-router、嵌套路由、路由传参、路由懒加载

文章目录

  • 一、React-Router的基本使用
    • 1. 安装及基本使用(路由映射配置)
    • 2. 路由跳转Link与NavLink
    • 3. Navigate导航
    • 4. 处理路径不存在的情况
  • 二、嵌套路由
  • 三、手动跳转 (类似编程式路由导航)
    • 1. 函数式组件
    • 2. 类组件实现手动跳转
  • 四、路由传参
    • 1. 路径设置占位符(params)
    • 2. search传递参数
  • 五、路由配置到单独的文件中(useRoutes)
  • 六、路由懒加载

一、React-Router的基本使用

1. 安装及基本使用(路由映射配置)

安装:

npm install react-router-dom

react-router最主要的时提供了一系列重要的组件,

(1) 设置路由模式
路由有两种模式:hash和history,对应react-router里的两个组件HashRouterBrowserRouter

HashRouter : 设置应用的路由采用hash模式

import { HashRouter } from 'react-router-dom';
root.render(
    <HashRouter>
      <App />
    </HashRouter>
);

BrowserRouter: 设置应用的路由采用history模式

import { HashRouter, BrowserRouter } from 'react-router-dom';
root.render(
    <BrowserRouter>
      <App />
    </BrowserRouter>
);

hash模式地址有#,history模式没有,开发更习惯用hash模式。

(2) 路由的映射配置
Routes组件:包裹所有的Route
Route: 用于设置路径与组件的对应关系,有两个属性:
path属性: 用于设置路径
element属性: 设置路径对应的组件.

import { Route, Routes } from 'react-router-dom'
import Home from './pages/Home'
import About from './pages/About'
export class App extends PureComponent {
  render () {
    return (
      <div>
        <div className="header">
          <h2>Header</h2>
        </div>
        <hr />
        <div className='content'>
          <Routes>
            {/* /home路径对应Home组件 */}
            <Route path='/home' element={<Home />} />
            <Route path='/about' element={<About />} />
          </Routes>
        </div>
        <hr />
        <div className="footer">
          <h2>Footer</h2>
        </div>
      </div>
    )
  }
}

在这里插入图片描述

2. 路由跳转Link与NavLink

LinkNavLink有点像vue里的router-link,to属性指定跳转的路径。最终都会被渲染称a元素。
两者的区别是:NavLink在被选中时,会自动加上active的类名。可以借此设置一些样式
在这里插入图片描述
点击不同的链接:

在这里插入图片描述

3. Navigate导航

该组件用于路由的重定向,当这个组件出现时,会跳转到对应的to路径中。

比如用户在登录页,当点击登录按钮时,自动跳转到home页面。

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

export class Login extends PureComponent {
  constructor() {
    super()
    this.state = {
      isLogin: false
    }
  }
  login () {
    this.setState({ isLogin: true })
  }
  render () {
    const { isLogin } = this.state
    return (
      <div>
        <h3>登录界面</h3>
         {/* isLogin为true,则跳转到home页面,否则显示按钮 */}
        {isLogin ? <Navigate to='/home' /> : <button onClick={e => this.login()}>登录</button>}
      </div>
    )
  }
}
export default Login

还有路由重定向问题;当路径为/时,需要重定向到别的页面,比如重定向到首页。

   <div className='content'>
     <Routes>
       {/* 重定向方式一: */}
       <Route path='/' element={<Navigate to='/login' />} />
       {/* 重定向方式二: */}
       <Route path='/' element={<Home />} />
       <Route path='/home' element={<Home />} />
       <Route path='/about' element={<About />} />
       <Route path='/login' element={<Login />} />
     </Routes>
   </div>

4. 处理路径不存在的情况

随便输入一个不存在的网址:

http://localhost:3000/#/abc

针对这种情况,一般会单独写一个NotFound的页面,提示用户页面不存在。
我们通过 设置路径为通配符*来映射到NotFound页面。

     <div className='content'>
       <Routes>
         {/* 重定向方式一: */}
         <Route path='/' element={<Navigate to='/login' />} />
         {/* 重定向方式二: */}
         <Route path='/' element={<Home />} />
         <Route path='/home' element={<Home />} />
         <Route path='/about' element={<About />} />
         <Route path='/login' element={<Login />} />
          {/* 路径一路匹配,匹配不到,说明路径不存在时,
             最后通过通配符*,跳转到NotFound页面 */}
         <Route path='/*' element={<NotFound />} />
       </Routes>
     </div>

二、嵌套路由

在这里插入图片描述
在content里显示Home组件的内容,Home组件里又显示推荐、排行等子组件。
现在要实现点击推荐、排行,显示对应的组件。

App.jsx

<div className='content'>
  <Routes>
    {/* 重定向 */}
    <Route path='/' element={<Navigate to='/home' />} />
    <Route path='/home' element={<Home />} >
      {/* 跳转到首页时,自动重定向到推荐页面 */}
      <Route path='/home' element={<Navigate to='/home/recommend' />} />
      {/* 嵌套路由 */}
      <Route path='/home/recommend' element={<HomeRecommend />} />
      <Route path='/home/rank' element={<HomeRanking />} />
      <Route path='/home/songmenu' element={<HomeSongMenu />} />
    </Route>
    <Route path='/about' element={<About />} />
   <Routes/>
<div/>

嵌套路由就是在Route的双标签里,写子组件的路由Route

由于是Home页面内嵌套显示其他页面,所以Home.js:

return (
  <div>
    <h3>Home</h3>
    <Link to='/home/recommend'>推荐</Link>
    <Link to='/home/rank'>排行</Link>
    <button>歌曲目录</button>
    {/* 占位,推荐,排行,歌曲目录的子组件在这儿展示 */}
    <Outlet />
  </div>
)
}

Outlet用于在父路由组件中子路由的占位,

三、手动跳转 (类似编程式路由导航)

react-router-dom提供了函数useNavigate,调用它会返回一个函数,执行该函数并将跳转路径传入就会实现跳转。但是useNavigate这个hook只能在函数式组件中使用。

1. 函数式组件

比如组件About

//App.jsx,在App组件中,其路由嵌套关系为:
 <Route path='/about' element={<About />} >
   <Route path='/about/singers' element={<Singers />} />
   <Route path='/about/platform' element={<Platform/>} />
 </Route>
 
//About.jsx 点击关于歌手按钮,实现页面跳转。
import React from 'react'
import { useNavigate, Outlet } from 'react-router-dom'
function About (props) {
  const nav = useNavigate()  //调用hook
  
  function navigateTo (path) {
    nav(path)
  }
  return (
    <div>
      <h2>About</h2>
      <button>关于平台</button>
      <button onClick={e => navigateTo('/about/singers')}>关于歌手</button>
       {/* 占位符,子组件 Singers的内容会展示在这里 */}
      <Outlet />
    </div>
  )
}

export default About

2. 类组件实现手动跳转

类组件要实现手动跳转,需要通过高阶组件给其注入useNavigate()返回的函数。

// with_router.js
import { useNavigate } from 'react-router-dom'
function withRouter (OriginComponent) {
// useNavigate 只有高阶组件在用,所以只能返回一个函数组件
  return function (props) {
    const nav = useNavigate()
    // nav放进对象里,注入到组件的props里
    return <OriginComponent {...props} router={{ nav }} />
  }
}
export default withRouter

组件内:

// Home组件,页面的图片在上一节嵌套路由出现过
export class Home extends PureComponent {
 navigateTo (path) {
   this.props.router.nav(path)
 }
 render () {
   return (
     <div>
       <h3>Home</h3>
       <Link to='/home/recommend'>推荐</Link>
       <Link to='/home/rank'>排行</Link>
       <button onClick={e => this.navigateTo('/home/songmenu')}>歌曲目录</button>
       {/* 占位 */}
       <Outlet />
     </div>
   )
 }
}
export default withRouter(Home)

四、路由传参

1. 路径设置占位符(params)

设置占位:

在这里插入图片描述
  Detail组件接收这种通过占位符传递的参数,需要用到一个hook函数useParams(),但它也只能在函数组件中使用。所以我们可以在高阶组件中使用useParams(),将得到的参数注入到Deatilprops中。

还是上面封装的那个高阶组件with_router.js

import { useNavigate, useParams} from 'react-router-dom'
function withRouter (OriginComponent) {
  return function (props) {

    // 1. 导航
    const nav = useNavigate()

    // 2. 动态路由参数--params
    const params = useParams()
    
    const router = { nav, params, }
    return <OriginComponent {...props} router={router} />
  }
}
export default withRouter

Detail.jsx

import React, { PureComponent } from 'react'
import withRouter from '../hoc/with_router'
export class Detail extends PureComponent {
  render () {
    const { params } = this.props.router
    return (
      <div>
        <h2>Detail</h2>
        <h3>获取到的id是:{params.id}</h3>
      </div>
    )
  }
}
export default withRouter(Detail)

在这里插入图片描述

2. search传递参数

参数通过?拼接到url中(类似query参数)。
在这里插入图片描述
与上边类似,可以借助useSearchParams()获取到路径里拼接的参数。由于这也是一个hook,所以我们也在高阶组件里调用useSearchParams(),得到参数,注入到组件的props中。

with_router.js

import { useNavigate, useParams, useSearchParams } from 'react-router-dom'

function withRouter (OriginComponent) {
  return function (props) {
    // 1. 导航
    const nav = useNavigate()

    // 2. 动态路由参数--params
    const params = useParams()

    // 3. 字符串参数(query)---
    const [searchParams] = useSearchParams()
    // console.log(searchParams.get('name'));
    const query = Object.fromEntries(searchParams.entries())

    const router = { nav, params, query }
    return <OriginComponent {...props} router={router} />
  }
}
export default withRouter

此处再补充一个hookuseLocation,也可以获取到字符串拼接的值

    const location = useLocation()
    console.log('location', location);

在这里插入图片描述

Login.jsx
组件接收数据:

export class Login extends PureComponent {
  render () {
    const { query } = this.props.router
    return (
      <div>
        <h3>登录界面</h3>
        <h4>query参数 --{query.name}--{query.age}</h4>
      </div>
    )
  }
}
export default withRouter(Login)

在这里插入图片描述

五、路由配置到单独的文件中(useRoutes)

总在App.jsx里写,不直观且代码较为复杂;
在这里插入图片描述
因此将路由的映射关系单独配置到到文件router/idnex.js

// 写了几个代表性的
const routes = [
  {
    path: './',
    element: <Navigate to='/home' /> //重定向
  },
  {
    path: '/home',
    element: <Home />,
    children: [
      {
        path: '/home',
        element: <Navigate to='/home/recommend' />
      },
      {
        path: '/home/recommend',
        element: <HomeRecommend />
      },
      {
        path: '/home/rank',
        element: <HomeRanking />
      }
    ]
  },
  {
    path: '/detail/:id',
    element: <Detail />
  },
... 
  {
    path: '*',
    element: <NotFound />
  },
]

export default routes

  在App组件中,用到useRoutes来将这些routes转换成原来的Routes这样的标签元素。但useRoutes是个hook,因此采用高阶组件将其注入到App组件中:

function withRouter (OriginComponent) {
  return function (props) {
    const routeEle = useRoutes(routes)
    return <OriginComponent {...props} routeEle={routeEle} />
  }
}

在这里插入图片描述

六、路由懒加载

(1)将路径改为懒加载
在这里插入图片描述
 改为懒加载的路径,会单独打到一个文件里,当用的时候再去加载这个文件。否则会全都打包到一个文件里。

(2)包裹Suspense 标签

import React, { Suspense } from 'react';
...
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <HashRouter>
   {/* 包裹Suspense 标签,当路由加载还未显示在页面上时,显示fallback里的内容 */}
    <Suspense fallback={<h3>路由懒加载中!!</h3>}>
      <App />
    </Suspense>
  </HashRouter>
);

http://www.kler.cn/news/357973.html

相关文章:

  • 【4.9】图搜索算法-BFS解打开转盘锁
  • 屏蔽小米电视广告的方法
  • 数据结构-复杂度
  • C语言导航 3.1运算符与表达式
  • 市场上几个跨平台开发框架?
  • 【含开题报告+文档+PPT+源码】基于SSM的景行天下旅游网站的设计与实现
  • C语言初阶小练习3(扫雷小游戏的代码实现及解读)
  • HCIE-Datacom题库_07_安全【11道题】
  • 解决DOTA-v2.0数据集上传结果至官网BUG: No space left on device
  • 性能工具之JMeter 通过Java API生成 BeanShell PreProcessor 脚本
  • Git客户端使用之命令行
  • 多表关联查询,join on 条件不生效,无法筛选记录
  • 单片机裸机程序 —— 设计模式
  • 机器人大功率主轴SycoTec 4060 ER-S汽车电机机芯焊缝铣削打磨加工
  • 数据结构-B树和B+树
  • java设计模式——装饰者模式
  • 详解equals底层原理
  • 【力扣打卡系列】滑动窗口与双指针(无重复字符的最长子串)
  • word取消自动单词首字母大写
  • OpenAI Prompt generation - 生成和优化Prompt的Prompt