react+typescript+vite+tailwind css学习总结(react19最新版)持续更新

一、新建项目

通过以下代码构建全新react+vite项目:

复制代码
npm create vite@latest my-react-app -- --template react-ts

新建完后将react与react-dom改为19.0.0

执行以下代码加载包:

复制代码
npm install

二、配置项目

1.eslint+prettier

参考vscode------Prettier插件保存自动格式化-腾讯云开发者社区-腾讯云

默认vite安装后都有eslint,然后开启eslint和prettier插件,然后在设置里edit format选prettier

新增

复制代码
    "format": "prettier --write \"src/**/*.+(js|ts|jsx|tsx)\""

package.json如下

复制代码
{
  "name": "flinkopsui",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "tsc -b && vite build",
    "lint": "eslint .",
    "preview": "vite preview",
    "format": "prettier --write \"src/**/*.+(js|ts|jsx|tsx)\""
  },
  "dependencies": {
    "flinkopsui": "file:",
    "prettier": "^3.4.2",
    "react": "^19.0.0",
    "react-dom": "^19.0.0"
  },
  "devDependencies": {
    "@eslint/js": "^9.19.0",
    "@types/react": "^19.0.8",
    "@types/react-dom": "^19.0.3",
    "@vitejs/plugin-react": "^4.3.4",
    "eslint": "^9.19.0",
    "eslint-config-prettier": "^10.0.1",
    "eslint-plugin-prettier": "^5.2.3",
    "eslint-plugin-react-hooks": "^5.0.0",
    "eslint-plugin-react-refresh": "^0.4.18",
    "globals": "^15.14.0",
    "typescript": "~5.7.2",
    "typescript-eslint": "^8.22.0",
    "vite": "^6.1.0"
  }
}

然后在根目录新建cjs文件配置prettier

复制代码
module.exports = {
  // 箭头函数只有一个参数时,可以省略参数的括号
  arrowParens: "avoid",

  // 对象字面量中括号与内部内容之间不加空格
  bracketSpacing: true,

  // 使用 Unix 格式的行结束符 (\n)
  endOfLine: "lf",

  // 每行的最大长度限制为 100 个字符
  printWidth: 100,

  // Markdown 文件中的文本是否换行,`preserve` 表示保持现状
  proseWrap: "preserve",

  // 在语句末尾添加分号
  semi: false,

  // 使用双引号而不是单引号
  singleQuote: false,

  // 缩进时每级使用 2 个空格
  tabWidth: 2,

  // 使用空格而不是制表符进行缩进
  useTabs: false,

  // 在多行对象或数组的最后一项后添加逗号(es5 支持的范围内)
  trailingComma: "es5",

  // 解析器设置为 TypeScript
  parser: "typescript",
  plugins: ["prettier-plugin-tailwindcss"],
};

如果一直报错执行底下:

复制代码
mv .prettierrc.js .prettierrc.cjs

设置完记得重启vscode

2.tailwind css

vite安装:参考Install Tailwind CSS with Vite - Tailwind CSS

3.ant design

三、react与JavaScript与JSX基础知识

1.标签

1.html标签必须闭合。

2.JSX片段必须首字母大写。

3.每段JSX只能有一个根节点,也就是必须有且要有一个<div></div>进行包裹。

3.Fragment:通过<></>可以不声明最外层div,避免块级元素重复使用。

2.属性

1.定义样式的class需要改为className。

2.style要使用JS对象,不能直接采用string形式,并且key要用驼峰命名法。

3.for要改为htmlFor。

3.事件

1.JSX监听事件分为点击事件、鼠标事件等等监听,onClick,采用onXXX的形式。

2.必须传入一个函数(还须注意在JSX里引用JSX需要{})=>形式为fn而不是fn(),若使用fn()则表示直接调用此函数,我们采用fn的形式类似于挂载。

3.传参如下:声明类型、在JSX中使用箭头函数进行传参,在(event)可以理解为 事件发生时 ,浏览器自动创建并传递的一个 事件对象,然后传递给方法。

复制代码
import type {MouseEvent} from "react";

const fn = (event: MouseEvent<HTMLButtonElement>)=>{
    event.preventDefault();
    console.log("123")
}

         <button onClick={(event) => fn(event)}>Click me</button>

4.JS变量或表达式

1.通过{/* */}在JSX中写注释。

2.通过{***}可以插入JS变量、函数、表达式。

5.条件判断

条件判断有三种:

1.通过&&进行判断=>适用于数据隐藏、显示。

2.三元表达式进行判断=>适用于数据切换显示。

3.函数进行判断=>通过显示函数的方式进行判断(注意:首字母要大写,函数与html都要大写)。

复制代码
 function HelloIf(){
    if(flag) return "hello"
    return "helloelse"
}

            {flag && <p>123456</p>}
            {flag ? <p>123</p> : <p>321</p>}
            <HelloIf></HelloIf>

6.循环

在JSX中使用map进行循环,并且要指定key,key必须是唯一的。

示例代码解释:首先新建list数组、通过map进行遍历,user为每一个遍历出来的元素,通过箭头函数进行返回,将其解构为username、name,key必须采用{}这样才使用的是对象而不是静态字符串。

注:在JSX里只要使用JavaScript就得先提前加上{}。

复制代码
const list = [
    {username:"1",name:"123"},
    {username:"2",name:321}
]

           <ul>
                {list.map(user=>{
                    const {username,name} = user
                    return <li key={username}>{name}</li>
                })}
            </ul>

四、react传参

五、react hooks

1.useState

useState当JSX中未使用的时候则不需要用useState,因为组件是个函数,并且useState会触发组件的更新,替代方法为useRef,并且useState为异步更新,也就是无法在JS中拿到最新的值(因为其实自己已经知道这个值)。

使用函数可以防止异步更新不合并。

1.2 useState值不可变

useState的值为不可变,也就是不能直接修改里面的值,要通过传入新的值的方式,通过新值或函数返回新值的方式更新,可以使用解构语法简化。

数组改变方式,用concat不能用push,因为concat返回一个数组新值。

1.3useState使用情况

所有组件的定义一定要首字母大写,要不然useState会报错。

1.4useState改变方法

1.4.1原始修改方法

增:concat

复制代码
  function add() {
    // setCount(count + 1)

    const r = Math.random().toString().slice(-3);
    setQuestionList(
      // 新增 concat
      questionList.concat({
        id: "q" + r,
        title: "问卷" + r,
        isPublished: false,
      })
    );
  }

删:fitter

复制代码
  function deleteQuestion(id: string) {
    // // 不可变数据
    setQuestionList(
      // 删除 filter
      questionList.filter(q => {
        if (q.id === id) return false;
        else return true;
      })
    );
  }

改:map

复制代码
  function publishQuestion(id: string) {
    setQuestionList(
      // 修改 map
      questionList.map(q => {
        if (q.id !== id) return q;

        return {
          ...q,
          isPublished: true,
        };
      })
    );
  }
1.4.2 immer修改方法
复制代码
  function add() {
    // setCount(count + 1)

    const r = Math.random().toString().slice(-3);
    // setQuestionList(
    //   // 新增 concat
    //   questionList.concat({
    //     id: "q" + r,
    //     title: "问卷" + r,
    //     isPublished: false,
    //   })
    // );
    // immer 的方式
    setQuestionList(
      produce(draft => {
        draft.push({
          id: "q" + r,
          title: "问卷" + r,
          isPublished: false,
        });
      })
    );
  }
  function deleteQuestion(id: string) {
    // // 不可变数据
    // immer 的方式
    setQuestionList(
      produce(draft => {
        const index = draft.findIndex(q => q.id === id);
        draft.splice(index, 1);
      })
    );
  }

  function publishQuestion(id: string) {
    // immer 的方式
    setQuestionList(
      produce(draft => {
        const q = draft.find(item => item.id === id);
        if (q) q.isPublished = true;
      })
    );
  }

2.useEffect

可以理解为监听,组件销毁时,组件特定值变化时([]里进行填写)

复制代码
  useEffect(() => {
    console.log("Component mounted");
    return () => {
      console.log("Component unmounted");
    };
  }, []); // 空依赖数组,表示仅在组件挂载和卸载时触发

3.useRef

跟Vue3的ref不同,Vue3的ref是操作响应式数据,而react的useRef是操作dom节点的。

去保存一个值,不影响页面显示,用useRef,因为useRef不会导致rerender,也就是页面更新,如果需要改变页面,则用useState。

复制代码
import { useRef } from "react";

const RefTest = () => {
  const select = useRef<HTMLInputElement>(null);
  function changeSelect() {
    const inputElem = select.current;
    if (inputElem) inputElem.select();
  }
  return (
    <div>
      <input ref={select} defaultValue={"Hello world"}></input>
      <button onClick={changeSelect}>改变数据</button>
    </div>
  );
};

export default RefTest;

4.useMemo

5.useCallback

6.自定义hook

首先自定义hook需要以use开头。

第一步:在src目录下新建hooks文件夹,并创建以use开头的hook的ts文件,由于没有使用JSX语法,所以只需要ts文件即可。

第二步:声明函数,并记得处理销毁事件,防止内存泄漏。

复制代码
import { useEffect, useState } from "react"

const useHooktest = () => {
    const [x, setX] = useState(0)
    const [y, setY] = useState(0)
    
    const mouseMoveHandler=(event: MouseEvent) => {
        setX(event.clientX)
        setY(event.clientY)
    }
    useEffect(() => {
        window.addEventListener('mousemove', mouseMoveHandler);
        return () => {
            window.removeEventListener('mousemove',mouseMoveHandler)
        }
    }, [])
    
    return {x,y}
}

export default useHooktest

在父组件进行引用并结构,即可正常使用自定义hook。

复制代码
// import List2 from "./list2";
// import RefTest from "./components/useRefTest";
import useHooktest from "./hooks/useHooktest";

function App() {
  const { x, y } = useHooktest();
  return (
    <div>
      <p>{x}</p>
      <p>{y}</p>
    </div>
  );
}

export default App;

7.hooks对比参考:​​​​​​

https://medium.com/@ksshravan667/14-days-of-react-day-5-react-hooks-usestate-useref-useeffect-usememo-usecallback-8599a14c4e2b

8.Hooks使用规则

七、CSS

1.使用css module解决相同命名

解决问题:比如一个页面引用多个组件,那么各个组件调用的css有相同命名的,通过以下方法解决。

vite自带css module,所以在创建文件的时候采用,xxx.module.css

引用的时候使用styles

复制代码
import styles from "./questionCard.module.css";

      <div className={styles["list-item"]}>123</div>

css module会自行给class进行命名

2.避免使用内联样式,并且通过使用classnames或clsx代替if else进行样式判断

3.采用sass

使用sass进行编写可以直接嵌套

复制代码
npm install sass

八、正式开始实战

1.新建pages页面、components组件

2.路由

2.1安装

复制代码
npm install react-router-dom

3.outlet

react实现固定区域与变化区域,通过outlet实现变化区域,就比如管理员需要固定的侧边栏进行导航,然后通过outlet进行对应渲染。

个人理解:

就是首先我有个底层的父路由,就比如有个/对应的MainLayout,那么它是顶层渲染,然后子组件是否是必须设置为它的children,然后react就是通过outlet去通过不同路由定位显示不同的子组件,然后vue就是通过router-view去定位显示不同的子组件,您看我这个理解对不对

第一步创建路由配置

复制代码
import { createBrowserRouter } from 'react-router-dom'
import MainLayout from '../layouts/MainLayout'
import Login from '../pages/Login'
import Home from '../pages/Home'
import NotFound from '../pages/404NotFound'

const router = createBrowserRouter([
  {
    path: 'login',
    element: <Login />,
  },
  {
    path: '/',
    element: <MainLayout />,
    children: [
      {
        path: 'home',
        element: <Home />,
      },
    ],
  },
  //*的意思是以上都不匹配执行 404 Not Found写在最后
  {
    path: '*',
    element: <NotFound />,
  },
])

export default router

第二步在app.tsx中引用

复制代码
import { RouterProvider } from 'react-router-dom'
import routerConfig from './router'
function App() {
  return <RouterProvider router={routerConfig}></RouterProvider>
}

export default App

3.渲染底层知识

4.路由导航

4.1useNavigate钩子

采用react router的useNavigate钩子进行导航

示例如下:

复制代码
import { useNavigate } from 'react-router-dom';

const ViewsPage = () => {
  const navigate = useNavigate();

  const goToTest1 = () => {
    navigate('/views/test1'); // 导航到 /views/test1 路由
  };

  return (
    <div>
      <button onClick={goToTest1}>Go to Test1</button>
    </div>
  );
};

export default ViewsPage;

4.2Link组件

复制代码
import { Outlet, Link } from 'react-router-dom';

const MainLayout = () => {
  return (
    <div>
      <header>
        <nav>
          <Link to="/home">Home</Link>
          <Link to="/about">About</Link>
        </nav>
      </header>
      <aside>固定的侧边栏</aside>
      <main>
        <Outlet /> {/* 动态内容 */}
      </main>
    </div>
  );
}

export default MainLayout;

4.3传递参数

4.4接收参数

采用useParams钩子进行参数的接收

采用useSearchParams钩子进行参数搜索

5.自定义标题与icon

全局在index.html中进行修改

单独修改使用ahooks(但是目前貌似还不支持react19)

第一步:

复制代码
npm install --save ahooks

九、细节理解

1.React.FC声明与传参理解

1.1Vue3与React19传递参数对比

父组件向子组件传递参数

子组件向父组件传递参数

子组件互相传递参数

1.2React.FC理解

相关推荐
安分小尧3 小时前
[特殊字符] 使用 Handsontable 构建一个支持 Excel 公式计算的动态表格
前端·javascript·react.js·typescript·excel
ElasticPDF-新国产PDF编辑器3 小时前
React 项目 PDF 批注插件库在线版 API 示例教程
react.js·pdf·json
帅帅哥的兜兜4 小时前
react中hooks使用
前端·javascript·react.js
吞掉星星的鲸鱼5 小时前
使用高德api实现天气查询
前端·javascript·css
拉不动的猪13 小时前
刷刷题49(react中几个常见的性能优化问题)
前端·react.js·面试
小满zs15 小时前
React-router v7 第二章(路由模式)
前端·react.js
yanxy51216 小时前
【TS学习】(18)分发逆变推断
前端·学习·typescript
大莲芒16 小时前
react 15-16-17-18各版本的核心区别、底层原理及演进逻辑的深度解析--react18
前端·javascript·react.js
编程社区管理员17 小时前
「2025最新版React+Ant Design+Router+TailwindCss全栈攻略:从零到实战,打造高颜值企业级应用
前端·react.js·前端框架