首页 > 其他分享 >react-router

react-router

时间:2023-02-20 00:13:21浏览次数:60  
标签:react import 组件 router 路由 页面

react-router

一、在react项目中安装路由

官方文档:https://reactrouter.com/en/v6.3.0/getting-started/installation#basic-installation

npm

$ npm install react-router-dom@6

 

二、使用react-route-dom

1、选择路由模式:在入口文件index.js中

  1. 选择路由模式:BrowserRouter 历史记录路由模式;HashRouter 哈希路由模式

  2. <BrowserRouter>

    <app/>

    </BrowserRouter> 路由模式包裹根组件

import React from "react";  // 引入react => 获取到react提供的api
import ReactDOM from "react-dom/client";    // 将虚拟dom => 真实dom
import "./index.css";
import App from "./App";    //引入根组件
import { BrowserRouter,HashRouter } from "react-router-dom";   // BrowserRouter => 选择路由模式 => history

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <BrowserRouter>
  {/* 
    这个里面的组件 如果要使用路由 就会采用history => 本质 provider => 在父组件中提供数据,在自己组件就是可以使用 react-router-dom 提供的api 提供的那些东西 => 路由模式, 路由api 
  */}
  {/* react => 组件渲染的结构 => 父子结构 */}
    <App />
  </BrowserRouter>
);

 

 

三、创建路由表:写组件和路径对应关系

  1. 在选择路由模式后,通过 react-router-dom提供的api 来实现,可以使用全局组件:

    1. Routes 路由表 2. Route 路由信息 3. Link 相当于a标签 可以跳转路由 4. OutLet 路由占位符

  2. 路由模块化:配置路由表

    1. 在sr目录下创建一个文件夹=》router/index.js文件 =》创建路由表=》就是一个组件

    2. 有几个属性:path 写路径 element写组件

    3. <Routes>

      <Route path="/login" element={<Login></Login>}></Route>

      </Routes>

    4. 在到根组件app.js中进行引入 =》使用这个组件

       

  3. 嵌套路由

    1. 在按个路由组件进行嵌套 => 直接添加路由信息组件

    2. 嵌套路径 的路径会进行拼接

    3. 根据路径匹配嵌套路由 => 路由占位符 <OutLet> </OutLet>=> 在哪里展示这个嵌套路由就需要在哪里写路由占位符

import { Routes, Route } from "react-router-dom";
// Routes =》 路由表
// Route  =>  路由信息

import { useNavigate } from "react-router-dom";
// 从首页跳转到login
// 语法: useNavigate() =》 返回值也是一个方法,这个方法有两个参数

// Link => 相当于A标签
// let routes =[
// {path:'/',component:'组件'}
// ]

// 四 创建路由表
// 通过react-router-dom提供的api 来实现
//  有几个属性 => path element

//  五 链式的路由跳转
// 方式 push , replace , go
// 1 push :浏览器历史栈中有记录,可以回退
// 2 reaplace: 浏览器历史栈没有记录,不可以回退
// 3 go   : 前进和后退

// 八 嵌套路由
// 概念:在页面级组件中展示页面级组件

// 用法: 1 配置嵌套路由

import Index from "../views/Index/Index";
import Login from "../views/Login/Index";
import Me from "../views/Me/Index";
import IndexShow from "../views/IndexShow/Index";
import NotFind from "../views/NotFind/Index";

function RouterList() {
  return (
    <Routes>
      <Route path="/" element={<Index></Index>}>
        {/* 
        嵌套路由
            1. 在按个路由组件进行嵌套 => 直接添加路由信息组件
            2. 嵌套路径 的路径会进行拼接
            3. 根据路径匹配嵌套路由 => 路由占位符 => 在哪里展示这个嵌套路由就需要在哪里写路由占位符
    */}
        <Route path="indexshow" element={<IndexShow></IndexShow>}></Route>
      </Route>
      <Route path="/login" element={<Login></Login>}></Route>
      <Route path="/Me" element={<Me></Me>}></Route>
      <Route path="*" element={<NotFind></NotFind>}></Route>
    </Routes>
  );
}

export default RouterList;

展示嵌套路由,在哪里展示这个嵌套路由就需要在哪里写路由占位符 "../views/Index/Index";

 return(
        <div>
            index
            <button onClick={()=>goPath()}>路由传递参数 可见</button>
            <button onClick={()=>goPath2()}>路由传递参数 不可见2</button>

            <Outlet></Outlet>
        </div>
    )

 

4、实现路由懒加载

作用:用户没有进入到这个页面,这个页面的代码就不会在首次加载项目的时候,加载处理,提供项目首次加载的速度

语法:React.lazy() 结合 Suspense

React.lazy() 语法 =》 React.lazy(()=>import('组件路径')) =》路由懒加载组件

Suspense 语法=》 < Suspense fallback ={先展示的组件(异步组件)} ></Suspense>

Suspense不能直接包围整个路由表,否则会出现页面创建两次的bug

哪些需要展示异步组件,路由懒加载的就包裹哪些组件即可

/* 
  十二: 路由懒加载
        作用:用户没有进入到这个页面,这个页面的代码就不会在首次加载项目的时候,加载处理,提供项目首次加载的速度


        // 语法 :React.lazy() 结合Suspense

        React.lazy()  语法 => React.lazy(()=>import('组件路径'))  => 路由懒加载组件

        Suspense  语法=> <Suspense fallback={先展示的组件}></Suspense>
        
        Suspense
*/

import { Routes, Route,Link } from "react-router-dom";
import React,{Suspense} from "react";

/* 
  路由懒加载 + 异步组件
    React.lazy(()=>{}) => 返回值 就是 我们的路由懒加载数据

    // Suspense =》 结合懒加载使用,当路由懒加载组件还没有显示,先加载Suspense 提供组件
   
*/

// 写一个公共的方法 处理懒加载组件=》他的返回值就是懒加载组件



import Index from "../views/Index/Index";
import Login from "../views/Login/Index";
// import Me from "../views/Me/Index";
// import IndexShow from "../views/IndexShow/Index";
import NotFind from "../views/NotFind/Index";

// 封装路由懒加载的方法
function ChangeLazyC(name){
       let Com
        Com  = React.lazy(()=>import(`../views/${name}/Index`))  //返回懒加载组件
        return <Com></Com>
}

function RouterList() {
  return (

  <Suspense fallback={<div>loading...</div>}>
    <Routes>

      <Route path="/" element={<Index></Index>}>
        <Route path="indexshow" element={ChangeLazyC('IndexShow')}></Route>
      </Route>

      <Route path="/login" element={<Login></Login>}></Route>

      <Route path="/Me" element={ChangeLazyC('Me')}></Route>

      <Route path="*" element={<NotFind></NotFind>}></Route>

    </Routes>
  </Suspense>
  );
}

export default RouterList;

优化封装 自动处理成 懒加载组

//写一个公共的方式 处理懒加载组件 =>他的返回值就是懒加载组件

function ChangeLazyC(name){
       let Com
        Com  = React.lazy(()=>import(`../views/${name}/index`))  //返回懒加载组件
        return <Com></Com>
}

4、在根组件App.js中引入路由表

  1. 在根组件中引入路由表

import './App.css';

import { Link } from 'react-router-dom';
// 引入路由表
import RouterList from './router/index'
import useRedirect from './useHooks/routerRedirect';
import useBeforEach from './useHooks/routerBeforEach';
import useRouteReEa from './useHooks/routerReEa';

// 创建路由表 => 全局组件 => react-router-dom

// Link => 相当于A标签
// let routes =[
  // {path:'/',component:'组件'}
// ]

function App() {
  // useRedirect();    // 路由重定向
  // useBeforEach();   // 路由守卫
  useRouteReEa();   // 路由重定向 路由守卫 合并
  return (
    <div className="App">
      
      <div>
        <Link to="/">首页</Link> | <Link to='/login'>登录</Link>
      </div>
      <RouterList></RouterList>    // 引入路由表
    </div>
  );
}

export default App;

 

四、链式的路由跳转

  1. 通过 react-router-dom提供的api : useNavigate()导航

  2. 语法:let navigate = useNavigate(); 返回值也是一个方法navigate,这个方法有两个参数,参数一:路由,参数二:配置项{ },改变跳转方式 和 路由传递参数

  3. navigate('/跳转路由',{跳转方式:true})

  4. 跳转方式:

  5. push:语法:navigate('/跳转路由'); 浏览器历史栈中有记录,可以回退;它是默认跳转方式;

  6. reaplace:语法:navigate('/路由', {replace:true}); 浏览器历史栈中没有记录,不可以回退

  7. go: 语法:navigate(1) 正数前进 ; navigate(-1) 负数后退

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

// 从首页跳转到 login
// 语法: useNavigate() => 返回值也是一个方法,这个方法有两个参数
    // 参数一:路由
    // 参数二:配置项 => {}  => 改变跳转方式 和 路由传递参数
    
// function Index(){
//     let navigate=useNavigate(); // 路由跳转的方式useRouter
//     // console.log(navigate)
//     const goLogin=()=>{
//         navigate('/login'); // 默认是push 跳转方式
//     }
//     const goLoginR=()=>{
//         navigate('/login',{replace:true});  // replace
//     }
//     const goLoginG=()=>{
//         navigate(1)
//     }

//     return(
//         <div>
//             <h2>这里是首页哦!</h2> 
//            <button onClick={()=>{goLogin()}}>去登录 push</button> 
//            <button onClick={()=>{goLoginR()}}>去登陆 replace</button>
//            <button onClick={()=>{goLoginG()}}>Go/Back go</button>
//         </div>
//     )
// }

// export default Index

// /* 
//     总结 路由跳转的方式

//         1 push => 默认的
//         2 replace => 需要自己进行配置   => useNavigate()
//         3 go    => useNavigate()   => 返回方法 它的参数写数字(正数前进,负数后退)
// */

 

五、路由传递参数

  1. 路由参数在路由地址上可见

  2. 传递路由参数: 字符串模板拼接(最多使用) navigate(/login?id${要传递的参数} && ids=300)

  3. 获取路由参数:通过 react-router-dom提供的api : useLocation() 1. useLocatinos(获取当前url上的信息); // 相当于vue-router中的useRoute路由信息 2. 语法:let location = useLocation(); 1. 通过location.search; 获取到的路由参数是一个字符串 2. 利用插件利用插件query-string 解析url上面的参数

  4. 路由参数在路由地址上不可见

  5. 传递路由参数: 1. 语法:navigate(/login,{state:{id:100}); // 通过state传参不可见

  6. 获取路由参数:

路由传参:

//  路由传递参数
function Index(){
    
    let navigate=useNavigate();

    // 1 可见  
    // 字符模板拼接 最多
    const goPath=()=>{
        let id=100;
        navigate(`/login?id=${100}&&ids=300`)
        }

    // 不可见
    const goPath2=()=>{
        navigate(`/me`,{
            state:{id:1100}
        })
    }

    return(
        <div>
            index
            <h2>这里是首页哦!</h2> 
            <button onClick={()=>goPath()}>路由传递参数,可见</button>

            <button onClick={()=>goPath2()}>路由传递参数,不可见2</button>
            <Outlet></Outlet>
        </div>
    );
}

export default Index;

获取到路由参数

import { useNavigate, useLocation,Outlet } from "react-router-dom";
import qs from "query-string";

// 获取到路由信息=》 路由参数可见 => 解析过来的参数是一个字符串

//  我们需要将这个字符串变成 =》 对象的形式 => 第三方库 query-string
// 1 项目中安装 =》 npm install query-string
// 2 在那里需要解析url 参数的地方引入 import qs from 'query-string'
// 3 使用它里面的一个方式qs.parse(需要解析的url地址)

// useLocation => 相 当于vue-router  useRoute
// 语法 =》 let location = useLocation()

// 获取到路由参数
// 1) 获取可见的路由参数

function Login() {
  let navigate = useNavigate();
  let location = useLocation();

  // 如果路由参数可以见 =》 获取到的路由参数是一个字符串 ?id=100&&ids=300  =》{id:100,ids:300}

  // 解决方法 -=》 通过第三方的一个库 query-string => 解决 url上面的参数
  console.log(location);
  console.log(qs.parse(location.search));

  const goPath = () => {
    navigate("/me");
  };

  const logins=()=>{
    alert('登录成功');
    sessionStorage.setItem('token','11111')
  }

  //  登录
  return (
    <div>
      <h2>这里是登录页哦!</h2>
      <button onClick={() => goPath()}>去个人页面 me</button>
        <button onClick={()=>{logins()}}>登录</button>
    </div>
  );
}

export default Login;

 

六、路由重定向

  1. 需要自己定义方法来处理:自定义hooks

1、自定义hooks

  1. 概念:

    1. 就是react 没有给我提供这个 hooks,我自己定义的方法,是按照一定的规则

    2. 以use 声明的方法

    3. 可以是 react 提供的hooks

  2. 案例:实现路由重定向 => 当我访问 首页的路径 => 重定向到首页展示路径

  3. 操作步骤:

    1. 在src目录下定义一个useHooks 存放自定义的hooks

    2. 再创建一个routerRedirect.js文件

    3. 在app文件中引入这个自定义的Hooks,直接调用

import {useLocation,useNavigate} from 'react-router-dom'
import {useEffect} from 'react'

function useRedirect(){
//   实例路由重定向  =》 当我访问 首页的路径 =》重定向到首页展示路径
// 1 知道当前的路径
let location = useLocation()

// 2 在路由跳转
let navigate = useNavigate()

//监听当前的路由信息
useEffect(()=>{
 
    if(location.pathname=='/'){
        navigate('/indexshow',{replace:true})
    }
},[location.pathname])
}

export default useRedirect

在App.js根组件直接使用:useRedirect() //自定义hooks,实现路由重定向

import RouterList from './router/index'
import useBeforEach from './useHooks/routerBeforEach'
import useRedirect from './useHooks/routerRedirect'

function App() {
    useRedirect() //自定义hooks,实现路由重定向
      useBeforEach()    //自定义hooks,实现路由守卫
  
  return (
    <div className="App">
        <RouterList></RouterList>
    </div>
  );
}
export default App;

 

七、路由守卫

1. 在react中=》我定义自定义hooks

  1. 处理内部页面和外部页面

  2. 案例:判断本地存储中是否有"token", 如果没有就跳转到登录页面

  3. 操作步骤

    1. 在src目录下定义一个useHooks 存放自定义的hooks

    2. 再创建一个routerRedirect.js文件

    3. 在app文件中引入这个自定义的Hooks,直接调用

    4. 在app根组件直接使用:useRedirect() //自定义hooks,实现路由守卫区分内部页面与外部页面

import { useLocation, useNavigate } from "react-router-dom";
import { useEffect } from "react";
function useBeforEach() {
  //在react中=》我定义自定义hooks=>
  //处理内部页面和外部页面

  let location = useLocation();
  let navigate = useNavigate();
  useEffect(() => {
    console.log(location);
    if (location.pathname != "/login") {
      //内部页面
      //判断用户是否登录
      if (!sessionStorage.getItem("token")) {
        // 没有登录
        //去登录页面
        navigate("/login", { replace: true });
      }
    }
  }, [location.pathname]);
}

export default useBeforEach;
合并路由守卫和路由重定向

发现这个路由守卫和路由重定向 都需要监听路由信息 =》进行合拼

import { useLocation, useNavigate } from "react-router-dom";
import { useEffect } from "react";

//这个自定义hooks => 1 实现路由重定向  2实现路由守卫=》判断内部页面和外部页面

function useRouterReEa() {
  let location = useLocation();
  let navigate = useNavigate();

  useEffect(() => {
    if (location.pathname != "/login") {
      //内部页面
      //判断用户是否登录
      if (!sessionStorage.getItem("token")) {
        // 没有登录
        //去登录页面
        navigate("/login", { replace: true });
      } else {
        //登录了
        if (location.pathname == "/") {
          navigate("/indexshow", { replace: true });
        }
      }
    }
  }, [location.pathname]);
}

export default useRouterReEa;

 

八、处理404页面

在路由表中配置路由

 <Route path='*' element={<NotFind ></NotFind >}></Route>

 

九、动态路由

  1. 动态路由:根据后端给的数据动态生成

function  ListItem(list){

      if(list.length>0){
          return  list.map((item,index)=>{
            return  <Route key={index} path="bashbord" element={LazyC('DashBord')}></Route>
          })
      }
}
  1. react组件的执行流程:

    1. 点击 Link 组件(a 标签)时,会修改浏览器url地址栏中的pathname

    2. 路由监听到 url 地址变化之后,得到最新的 pathname,再遍历所有的 Route 组件。使用 pathname和 Route 中的 path(路由规则) 进行比对,找到匹配的 Route

    3. 当路由规则(path)能够匹配地址栏中的 pathname 时,就展示该Route 组件的内容

  2. 总结:

    1 根据后端给的数据动态生成 =>2 点击登录获取到权限 => 去到内部页面 => 需要重新执行路由表,只能执行一次

 

十、路由优化

  1. react执行机制:只要路由地址发生改变,路由表就会重新执行(所以路由重定向/导航组件不能发在App根组件中,而要放在Layout组件中)

  2. react 路由组件执行流程 => 去到内部页面,需要在执行路由表

  3. 总结:根据后端给的数据动态生成 =》 2 点击登录获取权限 =》 去到内部页面 =》需要重新执行路由表,只能执行一次

  4. Suspense不能直接包围整个路由表,否则会出现页面创建两次的bug

    哪些需要展示异步组件,路由懒加载的就包裹哪些组件即可

    用法见下面代码:

Layout/layout.js文件

import { Outlet } from "react-router-dom";
import "./layout.css";
import useRouterReEa from "../useHooks";


function Layout() {
  // react执行机制:只要路由地址发生改变,路由表就会重新执行(所以路由重定向/导航组件不能发在App根组件中,而要放在Layout组件中)
  useRouterReEa();
  // 这个侧边栏导航的数据需要动态生成
  // 权限: 1 基础版本 => 前端 => 内部页面和外部页面 =》 路由守卫 后端:内部接口和外部接口     官网
  //        2 进阶版本 =》 后台管理系统  =》 页面 =》 1 侧边栏导航 2 动态路由
  //        3 中级版本 =》 后台管理系统  =》 自己可以设置权限

  // 这个侧边栏导航的数据需要的动态生成 =》 根据用户登录的时候获取
    let navList = ["dashBord","order","Index"];
    
  return (
    <div>
    <div className="header">内部管理系统</div>
      <div className="layout">
        <div className="leftNav">
            {
                navList.map((item,index)=>{
                    return (
                        <div key={index}>{item}</div>
                    )
                })
            }
        </div>
        <div className="rightNav">
            <Suspense fallback={<div>loading...</div>}>    
                <Outlet></Outlet>
            </Suspense>
        </div>
      </div>
    </div>
  );
}

export default Layout;

router/index.js文件

import { Routes, Route } from "react-router-dom";
import React, { Suspense } from "react";

import Layout from "../Layout/layout";
import Login from "../views/Login/index";


// 路由懒加载
function LazyC(name) {
  let Com;
  Com = React.lazy(() => import(`../views/${name}/index`));
  return <Com></Com>;
}

function RouterList() {

console.log('路由表');

  // 需要获取到根据权限登录的时候后端返回的数据

  // 因为登录页面 =》 用户第一次进入需要加载页面 =》['dashBord','Index','Play']

  let navList=['dashBord','Index','Play']

  return (
    <Suspense fallback={<div>loading...</div>}>        // 把这里注释掉,放到包裹到具体的组件上
      <Routes>
        <Route path="/login" element={<Login></Login>}></Route>
        <Route path="/layout" element={<Layout></Layout>}>
            {/* /layout/bashbord */}
            {ListItem(navList)}
         
        </Route>
      </Routes>
    </Suspense>        // 把这里注释掉,放到包裹到具体的组件上
  );
}

function ListItem(list){
  if(list.length>0){
    return list.map((item,index)=>{
      return(<Route key={index} path="dashbord" element={LazyC("DashBord")}></Route>)
    })
  }
}

// 2 react 路由组件执行流程 =》 去到内部页面,需要在执行路由表 =》 redux(项目中讲)

// 总结 =》
  // 1 根据后端给的数据动态生成 =》 2 点击登录获取权限 =》 去到内部页面 =》需要重新执行路由表,只能执行一次

export default RouterList;

 

标签:react,import,组件,router,路由,页面
From: https://www.cnblogs.com/chccee/p/17135986.html

相关文章

  • vue3-router使用
     1.引入routernpminstallvue-router@4 2.创建文件夹router,并创建index.js文件import{createRouter,createWebHashHistory}from"vue-router"constrouter=cr......
  • #yyds干货盘点 react笔记之学习之完成添加功能
    前言我是歌谣我有个兄弟巅峰的时候排名c站总榜19叫前端小歌谣曾经我花了三年的时间创作了他现在我要用五年的时间超越他今天又是接近兄弟的一天人生难免坎坷大不了从......
  • #yyds干货盘点 react笔记之学习之完成删除功能
    前言我是歌谣我有个兄弟巅峰的时候排名c站总榜19叫前端小歌谣曾经我花了三年的时间创作了他现在我要用五年的时间超越他今天又是接近兄弟的一天人生难免坎坷大不了从......
  • react 两侧小图 轮播图
    ​​git地址​​​​体验地址https://hongbin.xyz/swipe​​import{FC,ReactElement,useEffect,useState}from"react";importstyled,{css,CSSObject}from"s......
  • 在react项目如何捕获错误
    在React项目是如何捕获错误的?一、是什么错误在我们日常编写代码是非常常见的举个例子,在react项目中去编写组件内JavaScript代码错误会导致 React 的内部状态被破坏,导......
  • 阿里前端经典react面试题集锦
    hooks为什么不能放在条件判断里以setState为例,在react内部,每个组件(Fiber)的hooks都是以链表的形式存在memoizeState属性中update阶段,每次调用setState,链表......
  • 面试官:React怎么做性能优化
    前言最近一直在学习关于React方面的知识,并有幸正好得到一个机会将其用在了实际的项目中。所以我打算以博客的形式,将我在学习和开发(React)过程中遇到的问题记录下来。这两......
  • 面试官让你说说react状态管理?
    开发者普遍认为状态是组件的一部分,但是同时却又在剥离状态上不停的造轮子,这不是很矛盾么?对于一个最简单的文本组件而言functionText(){const[text,setText]=......
  • 腾讯前端经典react面试题(附答案)
    React性能优化在哪个生命周期?它优化的原理是什么?react的父级组件的render函数重新渲染会引起子组件的render方法的重新渲染。但是,有的时候子组件的接受父组件的数据没有......
  • react小案例:发表评论功能
      ////导入包importReactfrom'react'importReactDOM from'react-dom'classAppextendsReact.Component{state={  //数据  comments:[ ......