首页 > 其他分享 >React-Router-Dom6 最佳实践

React-Router-Dom6 最佳实践

时间:2024-11-07 18:41:47浏览次数:4  
标签:function return router React Dom6 path Router id 路由

React-Router-Dom6 最佳实践

React-Router-Dom6 最佳实践

一咻 一咻 世界都变了   6 人赞同了该文章 ​ 展开目录  

react-router-dom6 使用

之前只使用过一次react-router,目前官方从5开始就已经放弃了原有的 react-router库,统一命名为 react-router-dom

实现效果

 

 

菜单的json如下,可根据下面的json动态生成菜单和路由信息。

[
  {
    id: '1',     // 唯一的id
    name: "模块一",  // 菜单名称 
    path: "/model1/dashboard",    // 菜单路径
    children: [                   // 子菜单
      {
        id: '2',
        name: "首页",
        path: "/model1/dashboard",
        icon: "",
      },
      {
        id: '3',
        name: "二级菜单",
        path: "/model1",
        icon: "",
        children: [
          {
            id: '6',
            name: "2-1-home",
            path: "/model1/home",
            icon: "",
          }
        ]
      },
    ],
  },
  {
    id: '4',
    name: "模块二",
    path: "/model2",
  },
  {
    id: '5',
    name: "模块三",
    path: "/model3",
  },
]

根据这个 json 动态生成路由和菜单信息

 

安装方法

$ yarn add react-router-dom

使用方法

这个demo采用的 vite搭建的本地环境。并添加 路由库。

$ yarn create vite react-router6-dom-study --template react

哦,对了本来不想使用组件库的,只想简单的使用一下,后面想着能不能做一个动态生成路由和菜单的功能,简单实现一下呢。于是就添加了 antd这个组件库

$ yarn add antd

 

启用全局模式 HashRouter和BrowserRouter 两种模式,

区分

  • HashRouter:URL中采用的是hash(#)部分去创建路由,类似www.example.com/#/
  • BrowserRouter:URL采用真实的URL资源 后续有文章会详细讲HashRouter的原理和实现,这里我们采用BrowserRouter来创建路由

main.jsx如下

import React from "react";
import ReactDOM from "react-dom";
import {BrowserRouter} from "react-router-dom";
import zhCN from "antd/lib/locale/zh_CN";
import "antd/dist/antd.css";
​
import "./index.css";
import App from "./App";
​
ReactDOM.render(
  <BrowserRouter>
    <App/>
  </BrowserRouter>,
  document.getElementById("root")
);
​

这样运行 yarn dev的时候在访问/的时候就可以看见这个组件了。

路由组件

hooks

Routes Route Link 使用

import './App.css';
import { Routes, Route, Link } from "react-router-dom"
function App() {
  return (
    <div className="App">
      <header className="App-header">
        <Routes>
          <Route path="/" element={<Home />}></Route>
          <Route path="/about" element={<About />}></Route>
        </Routes>
      </header>
    </div>
  );
}
function Home() {
  return <div>
    <main>
      <h2>Welcome to the homepage</h2>
    </main>
    <nav>
      <Link to="/about">about</Link>
    </nav>
  </div>
}
function About() {
  return <div>
    <main>
      <h2>Welcome to the about page</h2>
    </main>
    <nav>
      <ol>
        <Link to="/">home</Link>
        <Link to="/about">about</Link>
      </ol>
​
    </nav>
  </div>
}
export default App;
​

嵌套路由

function App() {
  return (
    <Routes>
      <Route path="user" element={<Users />}>
        <Route path=":id" element={<UserDetail />} />
        <Route path="create" element={<NewUser />} />
      </Route>
    </Routes>
  );
}

当访问 /user/123 的时候,组件树将会变成这样

<App>
    <Users>
        <UserDetail/>
    </Users>
</App>

如果只是内部组件修改,也可以采用<Outlet/>来直接实现,如下所示

function App() {
  return (
    <Routes>
      <Route path="user" element={<Users />}>
        <Route path=":id" element={<UserDetail />} />
        <Route path="create" element={<NewUser />} />
      </Route>
    </Routes>
  );
}
function Users() {
  return (
    <div>
      <h1>Users</h1>
      <Outlet />
    </div>
  );
}
​

index路由

index属性解决当嵌套路由有多个子路由但本身无法确认默认渲染哪个子路由的时候,可以增加index属性来指定默认路由

function App() {
  return (
    <Routes>
      <Route path="/" element={<Layout />}>
        <Route index element={<About />} />
        <Route path="user" element={<User />} />
        <Route path="about" element={<About />} />
      </Route>
    </Routes>
  );
}

这样当访问/的时候<Outlet/>会默认渲染About组件

路由通配符

整个react-router支持以下几种通配符

/groups
/groups/admin
/users/:id
/users/:id/messages
/files/*
/files/:id/*

这里的*只能用在/后面,不能用在实际路径中间

关于NotFound类路由,可以用*来代替

function App() {
  return (
    <Routes>
      <Route path="/" element={<Home />} />
      <Route path="dashboard" element={<Dashboard />} />
      <Route path="*" element={<NotFound />} />
    </Routes>
  );
}
​

获取参数 useParams 和useSearchParams

假设现有App路由

function App() {
 return (
   <Routes>
     <Route path="user" element={<Users />}>
       <Route path=":id" element={<UserDetail />} />
       <Route path="create" element={<NewUser />} />
     </Route>
   </Routes>
 );
}

那么在UserDetail内部需要用useParams来获取对应的参数

import { useParams } from "react-router-dom";
​
export default function UserDetail() {
  let params = useParams();
  return <h2>User: {params.id}</h2>;
}

useSearchParams相对复杂,他返回的是一个当前值和set方法

 let [searchParams, setSearchParams] = useSearchParams();

使用时可以用searchParams.get("id")来获取参数,同时页面内也可以setSearchParams({"id":2})来改变路由,这样当访问 http://URL/user?id=111 时就可以获取和设置路径

useNavigate

useNavigate是替代原有V5中的useHistory的新hooks,其用法和useHistory类似,整体使用起来更轻量,他的声明方式如下:

declare function useNavigate(): NavigateFunction;
​
interface NavigateFunction {
  (
    to: To,
    options?: { replace?: boolean; state?: State }
  ): void;
  (delta: number): void;
}
复制代码
  //js写法
  let navigate = useNavigate();
  function handleClick() {
    navigate("/home");
  }
  //组件写法
  function App() {
     return <Navigate to="/home" replace state={state} />;
  }
  //替代原有的go goBack和goForward
 <button onClick={() => navigate(-2)}>
    Go 2 pages back
  </button>
  <button onClick={() => navigate(-1)}>Go back</button>
  <button onClick={() => navigate(1)}>
    Go forward
  </button>
  <button onClick={() => navigate(2)}>
    Go 2 pages forward
  </button>

嗨,中途床图 gitee还坏了,不得不换阿里的 oss 了。

闪屏问题

中途采用了 lazy 加载页面,所以就会造成闪屏,在代码中也有体现,最后决定采用局部加载的方式,来渲染二级路由,具体可以参见代码仓库,简单来说就是 LayoutPage(公共布局组件不使用懒加载的方式)。

权限思路

动态菜单

function genMenu(menuConfig) {
  return menuConfig.map(menuItem => {
    if (menuItem.children) {
      return <SubMenu
        key={menuItem.id}
        icon={<NotificationOutlined/>}
        title={menuItem.name}
      >
        {genMenu(menuItem.children)}
      </SubMenu>
    } else {
      return <Menu.Item key={menuItem.id} path={menuItem.path}>{menuItem.name}</Menu.Item>
    }
  })
}
            <Menu
              mode="inline"
              defaultSelectedKeys={["1"]}
              defaultOpenKeys={["sub1"]}
              onSelect={handleSelect}
              style={{height: "100%", borderRight: 0}}
            >
              {genMenu(menu[0].children)}
            </Menu>

 

动态路由

// 经过分析发现  菜单是有父子关系的 , 而路由没有,子路由都属于 LayoutPage 的子路由
​
// path 命名采用 驼峰命名法 helloWorld
// 组件的目录命名采用 HelloWorld 命名方式
// 所以就需要编写一个函数  将 path /helloWorld 转换成 /HelloWorld ,也就是/后面的第一个字符准换成大写的
​
function convertPath (path) {
  let arr = path.split('/')
  //  forEach 调用的时候 item 如果普通类型如果给 item 重新赋值 则不会修改原始值
  //  如果是引用类型  直接改变指针的指向则原始值不会被修改
  //  如果是引用类型  在原来引用的基础上修改会修改原始值
  return arr.map(item => {
    if (item) {
      return item[0].toUpperCase() + item.substring(1)
    }else {
      return item
    }
  }).join('/')
}
​
let router = [
  {
    path: "/login",
    element: LazyWrapper('Login'),
  },
  {
    path: "/",
    element: <LayoutPage/>,
    children: [],
  },
];
​
// 包装 React.lazy函数
function LazyWrapper(path) {
  const Component = lazy(() => import(`../pages${path}`))
  return (
    <Suspense fallback={<div>loading</div>}>
      <Component/>
    </Suspense>
  );
}
​
// 收集所有的叶子节点,生成路由信息
function genRouter(menuConfig, router) {
  menuConfig.forEach(menuItem => {
    if(!menuItem.children) {
      router.push({
        path: menuItem.path,
        element: LazyWrapper(convertPath(menuItem.path))
      })
    }else {
      genRouter(menuItem.children, router)
    }
  })
}
genRouter(menu[0].children, router[1].children)

 

代码仓库地址

react-router-dom-6

发布于 2022-03-27 21:55

标签:function,return,router,React,Dom6,path,Router,id,路由
From: https://www.cnblogs.com/sexintercourse/p/18533766

相关文章

  • React学习笔记(六) Create React App
    React学习笔记(六)CreateReactApp 1、介绍CreateReactApp是官方支持的创建单页应用程序的方法,可以帮助我们快速搭建一个繁杂的脚手架我们可以直接使用命令 npminstallcreate-react-app-g 全局安装CreateReactApp然后使用命令 create-react-app<project-na......
  • 高性能的Reactor和Proactor模式学习
    0、引言在上一篇的笔记中,我们学习了操作系统提供的高效I/O管理技术,主要用于解决服务器在高并发场景下的资源浪费和瓶颈问题。但是在实际的代码编写中,要是我们都全部调用底层的I/O多路复用接口来编写网络程序这种面向过程的方式,必然会导致开发的效率不高。于是在这一章节,我们来学......
  • React系统学习之路
    React系统学习之路学习目录第1章:React入门介绍React的基本概念和应用场景安装Node.js和npm创建第一个React应用React的JSX语法组件的基本结构和生命周期第2章:组件与状态管理函数组件与类组件的区别状态(State)和属性(Props)的使用受控组件与非受控组件高阶组件(HOC)的概念和......
  • vuex、vue-router实现原理
    Vuex和VueRouter是Vue.js生态系统中非常重要的两个库,分别用于状态管理和路由管理。它们各自的实现原理如下:Vuex实现原理1.状态管理Vuex是一个专为Vue.js应用程序开发的状态管理模式。它使用集中式的存储管理所有组件的状态,并以一种可预测的方式来确保状态以一种可追......
  • React.memo vs. useMemo: Major differences and use cases
    from:  https://blog.logrocket.com/react-memo-vs-usememo/ Memoization isoneofthewaystooptimizeperformance.Inthisarticle,we’llexplorehowitworksinReact.Whatismemoization?Insimpleterms,memoizationisaprocessthatallowsustocac......
  • Jest进阶知识:深入测试 React Hooks-确保自定义逻辑的可靠性
    测试ReactHooks在React开发中,Hooks是一个非常重要的功能模块,允许开发者在函数组件中使用状态和其他React特性。自定义Hooks作为一种公共逻辑的抽离,经常被多个组件复用,因此对其测试是非常必要的。然而,由于Hooks必须在组件内部使用,直接测试它们并不像普通函数那......
  • Vue项目中动态路由与权限控制:router.beforeEach的使用及无token重定向登录页
    在现代前端项目中,权限控制是一个非常重要的环节。VueRouter作为Vue官方的路由管理器,为我们提供了强大的路由管理功能。在本文中,我们将探讨如何在Vue项目中使用router.beforeEach钩子函数来实现动态路由权限控制,并在用户未登录时自动重定向到登录页。步骤一:登录并获取Token首......
  • 腿夹腿,带你用react撸后台,系列三(布局和鉴权篇)
    Github地址|文档|在线预览|主题版在线预览react-antd-console是一个后台管理系统的前端解决方案,封装了后台管理系统必要功能(如登录、鉴权、菜单、面包屑、标签页等),帮助开发人员专注于业务快速开发。项目基于React18、Antdesign5、Vite和TypeScript等新......
  • 新建一个react+vite+tailwindui项目
    创建Vite项目使用Vite创建一个新的React项目:npmcreatevite@latestmy-react-app--templatereactmy-react-app是你的项目名称,你可以根据需要更改。进入项目目录进入你刚刚创建的项目目录:cdmy-react-app安装TailwindCSS在项目中安装TailwindCSS及其依......
  • React
    渲染原理React其实是一个从上而下的组件树React的jsx通过createElement会重新变成js对象,因为js的资源比DOM来的要便宜得多,当组件树都创建完成之后,会进行一个diff算法,对节点进行一个懒更新,其实他循环的时候需要的那个key属性其实就是用来更准确地找到需要更新的地方,更节省资源......