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理解

相关推荐
千码君20163 小时前
React Native:为什么带上version就会报错呢?
javascript·react native·react.js
!win !3 小时前
一文搞懂Flex弹性布局空间分配规则
css·flex
zheshiyangyang4 小时前
Sass开发【四】
前端·css·sass
知识分享小能手4 小时前
React学习教程,从入门到精通,React 前后端交互技术详解(29)
前端·javascript·vue.js·学习·react.js·前端框架·react
lvchaoq4 小时前
react的依赖项数组
前端·javascript·react.js
打小就很皮...5 小时前
React实现文本markdownit形式
前端·react.js·前端框架
科技林总6 小时前
【TS3】搭建本地开发环境
学习·typescript
tyro曹仓舒9 小时前
彻底讲透as const + keyof typeof
前端·typescript
徐小夕@趣谈前端9 小时前
pxcharts多维表格编辑器Ultra版:支持二开 + 本地化部署的多维表格解决方案
大数据·javascript·react.js·编辑器·开源软件·r-tree·多维表格