用React给XXL-JOB开发一个新皮肤(二):目录规划和路由初始化

目录

  • 一. 简述
  • 二. 目录规划
  • 三. Vite 配置
    • 3.1. 配置路径别名
    • 3.2. 配置 less
  • 四. 页面
    • 4.1. 入口文件
    • 4.2. 骨架文件
    • 4.3. 普通页面
  • 五. 路由配置
  • 六. 预览启动

一. 简述

上一篇文章我们介绍了项目初始化,此篇文章我们会先介绍下当前项目的目录规划,接着对vite 配置以便我们后续的开发,最后会根据 xxl-job 的页面创建我们项目的页面并配置路由信息。

二. 目录规划

一般来说前端项目可以分为下面几个部分:页面、路由、状态管理、静态资源、工具方法。结合我们的项目我调整了下项目的目录结构如下:

  • api:存放 api 定义
  • assets:存放静态文件
  • components:公共组件
  • hooks:公共的 React Hooks
  • pages:存放页面
  • router:路由信息
  • store:存放状态管理文件
  • types:定义的接口交互的接口
  • utils:常用的一些工具类
    在这里插入图片描述

如果有其他的目录结构设计,可以评论区交流!

三. Vite 配置

上面我们规划了项目的目录结构,接着我们配置下 vite

3.1. 配置路径别名

配置路径别名之后可以省去写冗长的相对路径。
在这里插入图片描述
我们只需要在vite.config.ts 中添加如下配置:

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import path from "path";

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react()],
  resolve: {
    alias: {
      "@": path.resolve(__dirname, "src"),
      "@assets": path.resolve(__dirname, "src/assets"),
      "@pages": path.resolve(__dirname, "src/pages"),
      "@store ": path.resolve(__dirname, "src/store"),
      "@images ": path.resolve(__dirname, "src/assets/images"),
    },
  }
})

另外还需要修改 tsconfig.json,否者引入路径会飘红。

{
  "compilerOptions": {
    
    ...
    
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"]
    }
  },
  ...
}

3.2. 配置 less

我们在项目中使用less 做样式管理,需要在vite.config.ts中配置如下:

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import path from "path";

// https://vitejs.dev/config/
export default defineConfig({
  
  ... 忽略
  
  css: {
    preprocessorOptions: {
      less: {
        // 全局变量
        modifyVars: {},
        javascriptEnabled: true,
      },
    },
  },
})

后续我们在实现切换主题的功能的时候还会在配置这个地方,现在先放一放。

四. 页面

xxl-job 的任务调度中心有登录页面和管理页面组成,而管理页面也是我们常规管理系统的页面结构(结构如下)。
在这里插入图片描述
所以菜单栏、头部、尾部相当于管理页面的骨架,内容部分是需要切换路由动态展示的。做过管理系统的同学们应该很快就可以大体规划出页面模块。下面看一下我在pages 目录下定义的页面模块如下:

  • course:使用教程
  • dispatch:调度日志
  • exception:异常页面
  • executor:执行器管理
  • layout:页面骨架
  • login:登录页面
  • task:任务管理
  • user:用户管理
  • index.tsx:入口文件

日常开发建议:在定义模块目录的时候,最好见名知意,路由表也最好和模块名称对应(遇到 BUG可以最快的定位到问题页面)。主打一个不防御编程。

4.1. 入口文件

在 index.tsx 中,我们会配置引入定义的路由和 antd 的配置组件,内容如下:

import {ConfigProvider} from "antd";
import { RouterProvider, createBrowserRouter } from "react-router-dom";
import RouterSpace from "@/router";
import zhCN from "antd/lib/locale/zh_CN";
import routers = RouterSpace.routers;

const Application = () => {
  return <ConfigProvider locale={zhCN}>
    <RouterProvider router={createBrowserRouter(routers)} />
  </ConfigProvider>
}

export default Application;

这里我们使用 ConfigProvider全局化配置:https://ant-design.antgroup.com/components/config-provider-cn,方便我们使用国际化和配置组件样式等,具体可以看文档。

其中<RouterProvider router={createBrowserRouter(routers)} />,是通过createBrowserRouter 创建一个路由表,然后通过RouterProvider向下传递。

这里需要注意下BrowerserRouterHashRouter的区别:

  • BrowerserRouter:利用H5 history API实现url地址改变,并通过 pushStatereplaceState 改变 URL,但不会触发浏览器的刷新。这使得单页应用程序可以像多页应用程序一样具有多个路由;虽然此路由更加自然、美观,但是刷新页面的时候请求服务器,可能会导致 404错误;
  • HashRouter:使用window.location.hash 属性和window.onhashchange事件。可以监听浏览器hash值得变化,去执行相应的Js切换网页。使用 URL 中的 hash#)部分来进行路由管理;正是因为路由信息是存储在 URL 的哈希部分,不会出发服务器请求,但是哈希符号,影响美观;

所以在正常项目中我们都是需要和服务端配置使用的,建议使用BrowerserRouter就可以,在一些涉及到登录认证、菜单权限的权限的时候BrowerserRouter会它的妙用。

4.2. 骨架文件

骨架文件是为了定义公共组件部分,并提取出动态组件部分,代码如下:

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

const LayoutPage = () => {
  return <div>
    {/* 菜单 */}
    <div>
      <Link to={'/xxl-job/report'}>运行报表</Link>
      <br/>
      <Link to={'/xxl-job/task'}>任务管理</Link>
      <br/>
      <Link to={'/xxl-job/dispatch'}>调度日志</Link>
      <br/>
      <Link to={'/xxl-job/executor'}>执行器分管理</Link>
      <br/>
      <Link to={'/xxl-job/user'}>用户管理</Link>
      <br/>
      <Link to={'/xxl-job/course'}>使用教程</Link>
      <br/>
      <Link to={'/login'}>退出登录</Link>
    </div>
    {/* 内容 */}
    <div>
      {/* 头 */}
      <div></div>
      {/* 内容 */}
      <div>
        <Outlet />
      </div>
    </div>
  </div>
}

export default LayoutPage

Outlet 是一个用于渲染子路由的组件。它通常与 Route 配合使用,用于在父路由中指定子路由的渲染位置。Outlet 充当了子路由渲染的占位符,告诉 React Router 在当前组件中的哪里渲染子路由。

LinkReact Router 提供的组件之一,用于在应用中创建导航链接。它通常用于代替传统的 <a> 标签,提供了一种在单页面应用(SPA)中进行客户端路由导航的方式,而无需进行页面的完整刷新。

下一篇文章会介绍 css 组件如何使用。

4.3. 普通页面

除了骨架和入口文件,其他模块暂时都是简单的普通页面,如下图:
在这里插入图片描述
这些模块都如 task 目录下的 index.tsx 文件内容都是类似,内容如下:

const TaskPage = () => {
  return <div>任务管理</div>
}

export default TaskPage;

这里需要注意函数名称的命名规则,在定义导出函数名称的时候,最好是模块 + Page,这样可以很好的区别其他组件和页面组件。

五. 路由配置

我们在入口文件中通过createBrowserRouter(routers)创建路由表,这里面的 routers 就是我们需要定义的路由表结构信息。

import {Navigate, RouteObject} from "react-router-dom";
import LoginPage from "@/pages/login";
import TaskPage from "@/pages/task";
import ReportPage from "@/pages/report";
import DispatchPage from "@/pages/dispatch";
import ExecutorPage from "@/pages/executor";
import UserPage from "@/pages/user";
import CoursePage from "@/pages/course";
import LayoutPage from "@/pages/layout";
import NotFoundPage from "@/pages/exception/404.tsx";

namespace RouterSpace {

  export const routers: RouteObject[] = [
    { path: '/login', element: <LoginPage /> },
    {
      path: '/xxl-job',
      element: <LayoutPage />,
      children: [
        { path: 'report', element: <ReportPage /> },
        { path: 'task', element: <TaskPage /> },
        { path: 'dispatch', element: <DispatchPage /> },
        { path: 'executor', element: <ExecutorPage /> },
        { path: 'user', element: <UserPage /> },
        { path: 'course', element: <CoursePage /> },
        { path: '404', element: <NotFoundPage /> },
        { path: "*", element: <Navigate to={'/xxl-job/404'} /> }
      ]
    },
  ]
}

export default RouterSpace;

后面我们会优化这块路由表,改为 lazy 加载。

这里我们需要注意下RouteObject,现阶段我们只使用了 pathelementchildren 三个属性,这里面还有很多重要的属性可以参看文档:https://reactrouter.com/en/main/route/route#type-declaration。

interface RouteObject {
  path?: string; // 指定路由的路径
  index?: boolean; // 默认子路由ßß
  children?: React.ReactNode; // 定义子路由,是一个包含其他RouteObject的数组。子路由的路径会相对于父路由的路径。
  caseSensitive?: boolean; // 表示路由是否区分大小写,默认为false
  id?: string; // 为路由指定唯一的标识符
  loader?: LoaderFunction; // 一个异步加载函数,用于动态加载路由组件。鉴权的时候使用
  action?: ActionFunction; // 定义路由的生命周期函数,用于在路由渲染前或渲染后执行一些操作
  element?: React.ReactNode | null; // 指定路由匹配时要渲染的 React 元素
  hydrateFallbackElement?: React.ReactNode | null;
  errorElement?: React.ReactNode | null; // 在发生错误时渲染的元素
  Component?: React.ComponentType | null;
  HydrateFallback?: React.ComponentType | null;
  ErrorBoundary?: React.ComponentType | null;
  handle?: RouteObject["handle"];
  shouldRevalidate?: ShouldRevalidateFunction; // 一个函数,用于定义路由是否应该重新验证
  lazy?: LazyRouteFunction<RouteObject>; // 用于懒加载路由的函数
}

其他属性的使用可以参考我的另一个开源项目:https://gitee.com/molonglove/go-react-admin.git,里面有关于动态路由、权限等与路由相关的使用。

这里还有注意点:{ path: "*", element: <Navigate to={'/xxl-job/404'} /> },这个路由定义需要放在最后,意味着如果路由匹配失败会跳转的路由地址。

六. 预览启动

执行 yarn dev查看执行效果,就可以看到如下的效果!
在这里插入图片描述
下一篇文章我们将介绍借助 antd 实现登录页面和管理页面的Layout骨架。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/309747.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

了解统计分类中的贝叶斯理论误差限

一、介绍 统计分类和机器学习领域正在不断发展&#xff0c;努力提高预测模型的准确性和效率。这些进步的核心在于一个基本基准&#xff0c;即贝叶斯理论误差极限。这个概念深深植根于概率和统计学&#xff0c;是理解分类算法的局限性和潜力的基石。本文深入探讨了贝叶斯错误率的…

实现多级缓存(Redis+Caffeine)

文章目录 多级缓存的概述多级缓存的优势 多级缓存的概述 在高性能的服务架构设计中&#xff0c;缓存是一个不可或缺的环节。在实际的项目中&#xff0c;我们通常会将一些热点数据存储到Redis或MemCache这类缓存中间件中&#xff0c;只有当缓存的访问没有命中时再查询数据库。在…

java基础之函数

函数 概念 是一段具有特定功能的代码, 特点为可以多次执行.通常情况下一个函数对应一个功能 语法 访问修饰符 static 返回值类型 函数名(形参列表){//操作语句 } public static void 函数名(){} 位置 类以内,其他函数以外,与主函数平级 调用 自定义函数必须经过调用才…

web缓存之nginx缓存

一、nginx缓存知识 网络缓存位于客户端和 "源服务器 "之间&#xff0c;保存着所有可见内容的副本。当客户端请求缓存中存储的内容时&#xff0c;它可以直接从缓存中检索内容&#xff0c;而无需与服务器通信。这样&#xff0c;网络缓存就 "接近 "了客户端&a…

Tomcat-快速使用

关于Tomcat的概念及来由在Tomcat基本知识中进行了介绍&#xff0c;下面我们直接上手快速使用起来。 一、快速使用 &#xff08;1&#xff09;tomcat下载 &#xff08;2&#xff09;解压缩 &#xff08;3&#xff09;启动程序 &#xff08;4&#xff09;访问tomcat&#xff1a…

牛刀小试---二分查找(C语言)

题目&#xff1a;在给定的升序数组中查找指定的数字n&#xff0c;并输出其下标 代码举例&#xff1a; #include <stdio.h> int main() {int arr[] { 1,2,3,4,5,6,7,8,9,10 };//给定的升序数组int left 0;//定义左下标int right sizeof(arr) / sizeof(arr[0]) - 1;//…

JS 高频面试题

JS 的数据类型有哪些&#xff0c;有什么区别 基本数据类型&#xff08;Undefined、Null、Boolean、Number、String、Symbol&#xff09; 引用数据类型&#xff08;对象、数组和函数&#xff09; 区别&#xff1a; 原始数据类型直接存储在栈&#xff08;stack&#xff09;中的简…

Oracle 19c OCP 1z0 082考场真题解析第27题

考试科目&#xff1a;1Z0-082 考试题量&#xff1a;90 通过分数&#xff1a;60% 考试时间&#xff1a;150min本文为云贝教育郭一军&#xff08;微信&#xff1a;guoyJoe&#xff09;原创&#xff0c;请尊重知识产权&#xff0c;转发请注明出处&#xff0c;不接受任何抄袭、演绎…

前端开发Docker了解

1&#xff0c;docker简介 docker主要解决了最初软件开发环境配置的困难&#xff0c;完善了虚拟机部署的资源占用多&#xff0c;启动慢等缺点&#xff0c;保证了一致的运行环境&#xff0c;可以更轻松的维护和扩展。docker在linux容器的基础上进行了进一步的封装&#xff0c;提…

模板 BIEE(三)如何直接查看表示层列获取的sql语句

举例 想查看如下数据 SELECT 0 s_0, “Financials - AR Overview”.“Facts - AR Turnover”.“Days Sales Outstanding” s_1 FROM “Financials - AR Overview” web查看结果 日志内容如何查看请见《模板 BIEE&#xff08;二&#xff09;》 如下是不勾选高速缓存的结果&am…

研发日记,Matlab/Simulink避坑指南(一)——Data Store Memory模块执行时序Bug

文章目录 背景 问题 排查 解决 总结 背景 在一个嵌入式软件项目中&#xff0c;客户要求高度可控的时序流&#xff0c;我使用一个全局工步&#xff0c;对整个软件进行控制调度。由于子任务比较多&#xff0c;分门别类放在几个嵌套的子系统中&#xff0c;不能使用Goto模块引…

Python 面向对象之单例模式

【一】单例模式概念 单例模式是一种设计模式&#xff0c;其核心思想是确保一个类只有一个实例&#xff0c;并提供一个全局访问点。单例模式通常用于管理共享的资源&#xff0c;例如配置信息、数据库连接、线程池等。关键点在于如何判断这个类是否已经实例化 通过模块导入&…

机器人制作开源方案 | 乒乓球自动拾取机器人

作者&#xff1a;刘众森、王森、王绘东、崔岳震、宋维鑫 单位&#xff1a;山东农业工程学院 指导老师&#xff1a;潘莹月、廖希杰 1. 场景调研 我们小组选择项目的任务方向乒乓球的捡取与存放&#xff0c;针对此问题我们研发了一款乒乓球自动拾取机器人。众所周知&#xff0…

[算法与数据结构][c++]:Static关键字和全局变量

Static关键字和全局变量 1. 生命周期、作用域和初始化时机2. 全局变量3. Static 关键字3.1 面向过程3.1.1 静态全局变量3.1.2 静态局部变量&#xff08;单例中会使用&#xff09;3.1.3 静态函数 3.2 面向对象3.2.1 类内静态成员变量3.2.2 类内静态成员函数 Reference 写在前面&…

查看Linux磁盘空间

(1)、该命令会列出当前系统所有挂载的文件系统以及它们的使用情况&#xff0c;包括总容量、已用空间、可用空间、使用百分比等信息 df -h如果查看某一个文件夹的,可以 df -h folderName (2)、计算指定目录下所有文件和子目录所占用的磁盘空间大小&#xff0c;并以人类可读的格…

自动化创建ETX用户帐号

在芯片设计行业&#xff0c;ETX是常见的远程访问环境。用户在通过ETX访问远程环境前必须首先加入ETX系统&#xff0c;然后通过profile分配相关的环境的访问权限。 通常这些操作在ETX WEB页面手工操作&#xff0c;如果我们期望实现用户帐号注册全自动化&#xff0c;就需要将以上…

Deepin操作系统SSH开启与配置文件修改,结合内网穿透实现公网远程连接

文章目录 前言1. 开启SSH服务2. Deppin安装Cpolar3. 配置ssh公网地址4. 公网远程SSH连接5. 固定连接SSH公网地址6. SSH固定地址连接测试 前言 Deepin操作系统是一个基于Debian的Linux操作系统&#xff0c;专注于使用者对日常办公、学习、生活和娱乐的操作体验的极致&#xff0…

基于Vue组合式API的实用工具集

简介 今天,给大家分享一个很实用的工具库 VueUse,它是基于 Vue Composition Api,也就是组合式API。支持在Vue2和Vue3项目中进行使用,据说是目前世界上Star最高的同类型库之一。 图片 官方地址:https://vueuse.org/ 中文地址:https://www.vueusejs.com/ github:https…

SD-WAN对企业网络升级的价值

在当今数字化飞速发展的时代&#xff0c;企业对网络的依赖越来越深&#xff0c;如何在确保IT正常运行的同时降低成本成为企业CIO和业务经理共同关注的焦点。SD-WAN的出现为企业组网带来了崭新的可能性&#xff0c;成为降低开支、提高效率和改善用户体验的重要工具。 企业在数字…

代码随想录-刷题第五十三天

1143. 最长公共子序列 题目链接&#xff1a;1143. 最长公共子序列 思路&#xff1a;动态规划五步曲&#xff1a; dp[i][j]&#xff1a;长度为[0, i - 1]的字符串text1与长度为[0, j - 1]的字符串text2的最长公共子序列的长度为dp[i][j]。 递推公式&#xff1a; 主要是两种情…