vite+react+ts+mobx+antd+react-router-dom+sass+tailwindcss

news2024/9/20 9:41:26

写了Vue项目比较多了,最近想换一下react技术栈,锻炼自己的技术,废话不多说,开始创建项目吧,写这篇博客也只是记录我创建的过程,不通的版本难免有坑,欢迎一起分享讨论下!

1、npm create vite  // 使用vite 创建项目,下面的图片就是创建的选择的配置,可以参考下

 创建了之后,就cd 进入对应的文件夹下,通过命令code . 打开vscode 软件,然后就是安装依赖了,这一步很简单啦。pnpm i 直接进行安装即可

安装好了依赖之后,项目正常跑起来了,即可,接下来就是配置目录文件,可以参考一下我的项目目录,这个目录都是自定义的,看自己的编程习惯即可,没有一个固定的标准,因为公司的项目我基本都是单兵作战。

 2、安装 antd UI 组件(默认安装都是最新版本的 antd UI 的)

pnpm i antd -S

我的项目都是用pnpm  来进行安装插件和依赖的,觉得 pnpm 比较好用,安装下来的镜像还是比较小的

3、安装好了之后,就是 引入 UI 的 css 了

可以直接在 入口文件中 main.tsx 直接引入

import 'antd/dist/reset.css';

4、也可以在自己在 src 目录下 创建一个 style 文件夹,里面放入一个index.css 文件,写上

@import 'antd/dist/reset.css';

两者的效果都是一样的,只是引入的 方式不一样,注意看,还是有区别的,css 中得加上 @ 符号

安装好了之后,在 App.tsx 试一下,基本就是成功的了,

注意,我这个安装方式是全部引入,不是按需加载

 5、在 vite.config.ts 配置项目路径,以及运行的端口号

// vite.config.js
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import path, { resolve } from "path";

export default defineConfig({
  server: {
    host: "0.0.0.0", //解决 vite use--host to expose
    port: 8888, //配置端口
    open: true, //配置默认打开浏览器
  },
  resolve: {
    alias: {
      "@": path.resolve(__dirname, "src"), //配置@别名
    },
  },
  plugins: [react()],
});

还得在 tsconfig.json 中配置一下路径

{
  "compilerOptions": {
    "target": "ESNext",
    "useDefineForClassFields": true,
    "lib": ["DOM", "DOM.Iterable", "ESNext"],
    "allowJs": false,
    "skipLibCheck": true,
    "esModuleInterop": false,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "module": "ESNext",
    "moduleResolution": "Node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx",
    "baseUrl": "./",  // 这个重要
    "paths": { //  // 这个重要
      "@/*": ["src/*"]
    }
  },
  "include": ["src"],
  "references": [{ "path": "./tsconfig.node.json" }]
}

重启一下项目,重新刷一边配置就可以了 其实 @/ 代表从 src 开始找到对应目录的文件夹 

 6、安装路由 react-router-dom v6 版本的

pnpm i react-router-dom -S // 默认安装就是最新的版本的

在main.tsx 中使用一下路由,也就是应用到整个 app 上

import React from "react";
import ReactDOM from "react-dom/client";
import { BrowserRouter } from "react-router-dom";
import { Provider } from "mobx-react";
import App from "./App";
import "@/style/index.css";
import store from "./store/index";

ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
  <React.StrictMode>
    <BrowserRouter> // 使用历史模式,
      <Provider store={store}> // 这个是仓库,mobx,晚点会讲
        <App />
      </Provider>
    </BrowserRouter>
  </React.StrictMode>
);

 然后就是新建 router 文件夹,里面放入对应的路由文件,我是模仿Vue 的路由过来写的

 我的写法是参考老大的写法,将子路由都放在 modules 中了,在通过 import.meta.globEager(./modules/*.tsx) 进行全部加载,加载回来之后,通过自己处理数据格式,里面也包含了 路由登录拦截了,都写在代码里了

// index.tsx

import { Navigate, Route, RouteProps } from "react-router-dom";
import BasicLayout from "@/layouts/BasicLayout/BasicLayout";
import SignIn from "@/pages/login";
import cookies from "js-cookie";
import {
  ReactElement,
  JSXElementConstructor,
  ReactFragment,
  ReactPortal,
} from "react";

const modules = import.meta.globEager("./modules/*.tsx");

let routerModuleList: any[] = [];

Object.keys(modules).forEach((key) => {
  const mod = modules[key].default || {};
  const modList = Array.isArray(mod) ? [...mod] : [mod];
  routerModuleList.push(...modList);
});

// 升序排序
routerModuleList = routerModuleList.sort((a, b) => {
  // a-b 小于0 升序,大于零,是降序
  return (a.sort || 99) - (b.sort || 100);
});

const routes: any = [
  {
    path: "/",
    element: <Navigate to={"/layout/homePage"} />,
  },
  {
    path: "/layout",
    element: <VerifyLogin element={<BasicLayout />} />,
    children: [],
  },
  {
    path: "/login",
    element: <login/>,
  },
];

// 实现路由拦截
function VerifyLogin(prop: { element: ReactElement }) {
  const isLogin = cookies.get("token");
  return isLogin ? prop.element : <Navigate to="/login" replace />;
}

routes[1].children = routerModuleList;

export default routes;

然后是子路由规范

子路由 具体的代码方式 

import { Navigate, Outlet } from "react-router-dom";
import Home from "@/pages/home/index";

const routes = [
  {
    sort: 1,
    path: "/layout/homePage",
    element: <Outlet />,
    meta: {
      title: "首页",
    },

    children: [
      {
        path: "/layout/homePage/homeDetail",
        element: <Home />,
        meta: {
          title: "首页详情",
        },
      },
    ],
  },
];

export default routes;

7、安装sass 

 npm install --save-dev sass

我直接使用了,并不需要安装sass-loader 进行编译了,我比较奇葩,我基本都是每个页面直接 index.scss 直接引入对应文件下的,并没有出现样式污染的问题,如果你的出现了,可以使用这个 index.module.scss  就是 利用了 module 这个关键字,进行样式隔绝,安装sass 并不用配置啥,直接拿来使用即可

 8、配置多环境的变量,通过更改package.json 文件,使用 --mode 指定了不同环境的运行配置,我是这样的

 

这个 根目录下创建不同对应的环境文件,当然后期我们会在项目中使用,

这样用,也可以自己答应一下 log 看一下即可,很简单的。


const { VITE_BASE_URL, VITE_NODE_ENV } = import.meta.env;

 9、安装 mobx

pnpm i mobx mobx-react -S

本来使用 redux 的,但是吧,整了很久了,没搞好,项目也不是很大,用mobx 也够用了,

具体的使用方法

index.ts 中

import MenuStore from "./menu";
class Store {
  menuStore: MenuStore;

  constructor() {
    this.menuStore = new MenuStore();
  }
}

export default new Store();

 menu.ts 中

import { runInAction, makeAutoObservable } from "mobx";

// 对初始化数据进行响应式处理 mobx v6不支持装饰器写法
export default class MenuStore {
  constructor() {
    makeAutoObservable(this);
  }

  // 导航
  breadcrumbData = [];
  // 处理面包屑导航
  currentPath(path: string) {
    this.breadcrumbData = treeFindPath(
      routes[1].children,
      (data) => data.path === path,
      "meta"
    );

// 发起请求
 async fetchProjects() {
        try {
            const projects = await fetchGithubProjectsSomehow()
            // await 之后,再次修改状态需要动作:
            runInAction(() => {
                this.githubProjects = filteredProjects
            })
        } catch (error) {
            runInAction(() => {
                this.state = "error"
            })
        }
    }


  //销毁组件时重置参数
  reset() {}
}

10、然后是安装 tailwindcss 了

pnpm i tailwindcss@latest postcss@latest autoprefixer@latest

安装成功之后,还得配置一下才行,执行命令

npx tailwindcss init 会在根目录下生成两个文件,如果没有的话,也可以自己创建的哈

分别是 一定是 tailwind.config.cjs、postcss.config.cjs 后缀一定是 cjs 才行,注意了

tailwind.config.cjs 文件配置

module.exports = {
  purge: ["./src/**/*.{js,jsx,ts,tsx}", "./public/index.html"],
  darkMode: false, // or 'media' or 'class'
  theme: {
    extend: {},
  },
  variants: {
    extend: {},
  },
  plugins: [],
};

postcss.config.cjs 文件配置

const tailwindcss = require("tailwindcss");

module.exports = {
  plugins: [tailwindcss("./tailwind.config.cjs"), require("autoprefixer")],
};

创建好了,就是引用 tailwindcss 的样式了,可以直接在 启动文件中 App.tsx 中引入 样式文件,也可以自己创建一个 总的style 文件中进行统一引入样式文件

 创建  tailwind.css  文件

@import "tailwindcss/base";
@import "tailwindcss/components";
@import "tailwindcss/utilities";

我的文件目录结构

 

11、 安装 reset 重置浏览器的重置样式

pnpm install --save normalize.css

总的 style 文件中进行引入,最终在引入到入口文件中 也就是main.tsx 中

@import 'antd/dist/reset.css';

@import './normal.scss';

import 'normalize.css/normalize.css' // 这个是安装的重置样式

@import './tailwind.css'

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【李老师云计算】Spark配置及Scala实现100个随机数找最大值

索引 前言1. Spark部署1.1 Spark下载1.2 解压Spark1.3 修改环境变量1.4 修改主机Spark配置文件1.4.1 slaves.template文件配置1.4.2 spark-env.sh.template文件配置 1.5 分享主机Spark到从机1.6 启动Spark集群(★重启后的操作)1.7 通过jps查看是否启动成功1.8 通过网页查看是否…

rk3568 适配摄像头 (mipi 单摄)

rk3568 适配摄像头 (mipi 单摄) MIPI CSI&#xff08;Mobile Industry Processor Interface Camera Serial Interface&#xff09;是一种用于移动设备的高速串行接口标准&#xff0c;用于连接图像传感器和图像处理器。MIPI CSI接口使用差分信号传输技术&#xff0c;将数据分为…

C/C++ 高精度(加减乘除)算法二进制优化

高级精度算法系列 第一章 简单实现 第二章 压位优化 第三章 二进制优化(本章) 文章目录 高级精度算法系列前言一、基本原理1、存储方式2、计算方式 二、关键实现1、整型转高精度数组&#xff08;二进制&#xff09;2、字符串转高精度数组&#xff08;二进制&#xff09;3、高精…

小程序进阶

1.1组件基础 自定义组件的结构与页面是一致的&#xff0c;即也包含有4个部分&#xff0c;分别为: .wxml 组件的布局结构 .js 组件的处理逻辑 .json 组件的配置文件 .wxstngs 组件的布局样式 1.1.1创建组件 通常将组件放到独立的目录components当中这个目录需要手动创建 …

Spring Boot的配置文件

目录 配置文件的作用 配置文件的格式 properties配置文件 格式 注释乱码问题 读取配置文件 properties的优缺点分析 YAML yml基本语法 yml配置的读取 注意事项:value的值加单双引号 配置对象 yml优点分析 properties和yml的区别 设置不同环境的配置文件 配置文件的…

Linux-搭建web服务器

综合练习&#xff1a;请给openlab搭建web网站 ​ 网站需求&#xff1a; ​ 1.基于域名[www.openlab.com](http://www.openlab.com)可以访问网站内容为 welcome to openlab!!! ​ 2.给该公司创建三个子界面分别显示学生信息&#xff0c;教学资料和缴费网站&#xff0c;基于[www.…

SpringCloud --- Ribbon负载均衡

一、负载均衡原理 SpringCloud底层其实是利用了一个名为Ribbon的组件&#xff0c;来实现负载均衡功能的。 那么我们发出的请求明明是http://userservice/user/1&#xff0c;怎么变成了http://localhost:8081的呢&#xff1f; 二、源码跟踪 为什么我们只输入了service名称就…

浅谈: 计算机—JVM—Java线程—池

计算机的基本组成 计算机的基本组成 计算机存储模型(CPU、寄存器、高速缓存、内存、外存) 现代计算机系统CPU和内存之间其实是有一个cache的层级结构的。比内存速度更快的存储介质(SRAM)&#xff0c;普通内存一般是DRAM&#xff0c;这种读写速度更快的介质充当CPU和内存之间的…

3 连续模块(二)

3.5 零极点增益模块 在控制系统设计和分析中&#xff0c;常用的函数包括 传递函数&#xff08;tf&#xff09;、零极点&#xff08;zpk&#xff09;和状态空间&#xff08;ss&#xff09;函数 传递函数&#xff08;tf&#xff09;&#xff1a;用于表示线性时不变系统的输入输出…

SQL Compliance Manager Crack

SQL Compliance Manager Crack 新的SQL CM云代理-扩展了当前SQL CM代理的功能&#xff0c;以支持EC2上Microsoft SQL服务器的远程审核。允许用户添加在共享网络位置上活动的SQL Server&#xff0c;以写入/读取数据并支持DBaaS SQL Server实例。云代理包含与当前SQL代理相同的行…

VS code 插件之中英文间自动添加空格

前言 不知道大家在开发过程中是不是会遇到写代码注释或者文本内容时中英文之间没有空格的情况&#xff0c;很多时候在写代码尤其是写注释的时候容易忘记加空格&#xff0c;但回过头来看又难以忍受&#xff0c;于是我就想着自己写一个 vscode 插件来解决这个问题&#xff0c;希…

跟我一起开启 linux 的学习吧

跟我学 CentOS 的安装 一、安装 VMware二、创建虚拟机三、安装 CentOS 7四、linux 的登录 一、安装 VMware VMware 计算机虚拟化软件 从官网 https://www.vmware.com/cn.html 下载并安装 这里就不再展示安装过程啦&#xff01; 有需要的可以 点击这里 →→→ VMware 下载安装过…

postgresql 源码结构分析

专栏内容&#xff1a;postgresql内核源码分析个人主页&#xff1a;我的主页座右铭&#xff1a;天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物&#xff0e; 目录 前言 源码下载 源码结构 核心代码目录 结尾 前言 本文对postgresql源码目…

进销存管理系统和ERP的工作原理和实现方式有何不同?

一、ERP是什么&#xff1f; ERP即企业资源规划&#xff08;Enterprise Resource Planning&#xff09;&#xff0c;是一种集成管理软件系统。它的目的是整合和规划各种企业资源和业务流程&#xff0c;包括财务、物流、采购、生产、销售等&#xff0c;以提高企业的管理效率和业…

Java -- IO流

IO流 主要用于读写数据 IO流按照流的方向可以分为以下两种&#xff1a; 输入流输出流 IO流按照操作文件类型可以分为以下两种&#xff1a; 字节流字符流 字节流可以操作所有类型的文件&#xff0c;而字符流只可以操作纯文本文件 #mermaid-svg-tfFZjSluOmEFUpyc {font-fam…

SVM-老师讲的真的很好!

支持向量机(Support Vector Machine) 如同逻辑回归一样,SVM是一个分类模型 目标 SVM解决分类模型的基本思路:什么是一个好的分类边界? SVM认为,好的分类决策边界应当是:类别边界的距离应当尽可能的远 目标函数 拉格朗日乘子法 那么我们的公式就可以写为

SIP协议之通话转接

一、介绍 在SIP协议应用中&#xff0c;有一个常用的功能叫通话转接&#xff0c;用于将接通后的通话转给第三方接听处理。 二、原理及流程 转接是通过SIP协议的一个扩展请求方法REFER实现的。呼叫转接由RFC5589(Session Initiation Protocol (SIP) Call Control - Transfer)定义…

(数字图像处理MATLAB+Python)第六章图像平滑-第一节:图像平滑概述和空间域平滑滤波

文章目录 一&#xff1a;图像中的噪声&#xff08;1&#xff09;图像噪声分类&#xff08;2&#xff09;图像噪声的数学模型&#xff08;3&#xff09;程序 二&#xff1a;空间域平滑滤波&#xff08;1&#xff09;均值滤波A&#xff1a;均值滤波原理B&#xff1a;示例C&#x…

203、【栈与队列】leetcode ——剑指 Offer II 040. 矩阵中最大的矩形 / 85. 最大矩形:暴力+单调栈(C++/Pyhont版本)

题目描述 Problem: 剑指 Offer II 040. 矩阵中最大的矩形 文章目录 题目描述解法一&#xff1a;暴力解法思路解题方法复杂度Code 解法二&#xff1a;单调栈解法 解法一&#xff1a;暴力解法 思路 首先&#xff0c; 按行获取到达某一元素位置时&#xff0c;之前与当前连续1的个…

【JUC高并发编程】—— 初见JUC

一、JUC 概述 什么是JUC JUC 是 Java并发编程的缩写&#xff0c;指的是 Java.util.concurrent 即Java工具集下的并发编程库 【说白了就是处理线程的工具包】 JUC提供了一套并发编程工具&#xff0c;这些工具是Java 5以后引入的&#xff0c;使得Java开发者可以更加方便地编写…