【前端】快速过一遍React全家桶2025

#王者杯·14天创作挑战营·第1期#

近两天更新完基本内容,后续长期更新,建议关注收藏点赞。


React 项目创建

用 Vite + TypeScript

npm create vite@latest react-demo -- --template react-ts

cd react-demo
npm install
npm run dev
react-demo/
├─ src/
│  ├─ App.tsx         # 主组件
│  ├─ main.tsx        # 入口文件(渲染 App)
│  └─ vite-env.d.ts   # Vite 的类型声明
├─ public/            # 静态资源
├─ index.html         # HTML 模板
├─ vite.config.ts     # 构建配置

JSX 基础

JSX 是 React 独有的语法扩展,它长得像 HTML,但其实是 JavaScript

语法示例
标签必须闭合<img src="..." />
表达式用 {}<h1>{1 + 1}</h1>
条件渲染{isLogin ? 'Welcome' : 'Please login'}
列表渲染{items.map(item => <li>{item}</li>)}
样式写法<div style={{ color: 'red' }} />
class 要写成 className<div className="box" />
function Hello() {
  return <h1>Hello, React!</h1>
}
//等价于
React.createElement('h1', null, 'Hello, React!')

//练习:写在App.tsx中

组件基础(props、事件、children)

每个组件就是一个函数(返回 JSX)
多个组件组合成完整页面
React 项目本质是“组件树”

function Welcome() {
  return <h1>欢迎来到 React!</h1>
}
//使用组件 直接写 <组件名 />
function App() {
  return (
    <div>
      <Welcome />
    </div>
  )
}
  • 响应事件
function Button() {
  const handleClick = () => {
    alert('按钮被点击了!')
  }
  return <button onClick={handleClick}>点击我</button>
}

function App() {
  return (
    <div>
      <Welcome name="小红" />
      <Button />
    </div>
  )
}

组件通信

  • 父传子——传参props
    React 中组件通过 props 来传递参数(和 Vue 的 props 一样)
    父组件传参,子组件接收
function App() {
  return <Welcome name="小明" />
}
function Welcome(props: { name: string }) {
  return <h1>Hello, {props.name}!</h1>
}
//解构简写
function Welcome({ name }: { name: string }) {
  return <h1>Hello, {name}!</h1>
}
  • 父传子——children插槽 (和 Vue 的 slot 类似)
    React 中组件可以“嵌套内容”,通过 props.children 实现。
function Card(props: { children: React.ReactNode }) {
  return <div className="card">{props.children}</div>
}

function App() {
  return (
    <Card>
      <h2>标题</h2>
      <p>这是正文内容</p>
    </Card>
  )
}
  • 子传父——传事件函数
function Parent() {
  const handleClick = (msg: string) => {
    alert('收到子组件消息:' + msg)
  }
  return <Child onSend={handleClick} />
}
function Child({ onSend }: { onSend: (msg: string) => void }) {
  return <button onClick={() => onSend('hello!')}>发消息</button>
}
  • 兄弟组件通信
    方法一:提升状态到共同的父组件
    方法二:使用 全局状态管理(Zustand、Redux、Context 等)
  • 全局通信Context API
    • 使用场景:
      当前主题、用户信息、登录状态、语言、权限等全局变量
      跨多层组件传值(比如 Layout → Sidebar → MenuItem)
    • 对比
特点Context APIZustand / Redux
状态管理简单全局状态复杂状态管理
使用场景小项目、轻量通信大型项目、模块化
性能优化手动优化(memo)自动优化 / 中间件支持
学习成本中等偏高(Zustand较低)
//创建上下文
// context/UserContext.tsx
import { createContext } from 'react'
export const UserContext = createContext<{ name: string }>({ name: '游客' })

//在顶层组件中提供上下文
// App.tsx
import { UserContext } from './context/UserContext'

function App() {
  return (
    <UserContext.Provider value={{ name: '张三' }}>
      <Child />
    </UserContext.Provider>
  )
}

//在任意子组件中消费
// Child.tsx
import { useContext } from 'react'
import { UserContext } from './context/UserContext'

function Child() {
  const user = useContext(UserContext)
  return <div>用户名:{user.name}</div>
}

状态管理基础(useState、useEffect、组件通信)

React 是响应式框架,UI 会随着 state 变化自动更新。

  • useState:状态管理的核心
import { useState } from 'react'

function Counter() {
  const [count, setCount] = useState(0)
  //useState(初始值) 返回 [值, 修改值的方法]
//每次调用 setCount() 会重新渲染组件
  return (
    <div>
      <p>当前计数:{count}</p>
      <button onClick={() => setCount(count + 1)}>加一</button>
    </div>
  )
}
  • useEffect:副作用处理
    像 Vue 的 onMounted、watchEffect,React 用 useEffect。
//组件挂载时执行一次(相当于 Vue 的 mounted)
import { useEffect } from 'react'

function App() {
  useEffect(() => {
    console.log('组件已挂载')
  }, []) // 空数组:只执行一次

  return <h1>Hello</h1>
}
//监听某个值的变化(相当于 watch)
useEffect(() => {
  console.log('count 变了', count)
}, [count]) // 依赖 count

条件渲染与列表渲染

  • 条件渲染(if 判断)
    React 不支持 v-if,用 JS 表达式解决,一个是三元表达式(最常用),一个是逻辑与。
const isLogin = true
return (
  <div>
    {isLogin ? <p>欢迎回来</p> : <p>请先登录</p>}
  </div>
)

{isLogin && <p>你已经登录</p>}
  • 列表渲染(map())
    和 Vue 的 v-for 类似,React 用 .map() 遍历数组。
const fruits = ['🍎', '🍌', '🍇']
return (
  <ul>
    {fruits.map((fruit, index) => (
      <li key={index}>{fruit}</li>
    ))}
  </ul>
)
//使用key的原因:React 用 key 来追踪每个元素,提高性能;通常用唯一 id 或 index。
  • 特殊情况处理(如列表为空)
{items.length === 0 ? <p>暂无数据</p> : items.map(...)}
{items.length === 0 && <p>暂无数据</p>}
  • 整合例子
    • 为什么用setList而不是list.push(‘新的事项’)?
      因为 React 的状态不能直接修改原数组,需要返回一个 新引用的数组,这样 React 才能检测到变化,重新渲染组件。
      在 React 中,状态更新函数(如 setList)是由 useState 钩子生成的,用来更新组件内部的状态。
    • React 中的状态更新函数(如 setList、setState)为啥是异步的
      为了批处理更新,只渲染一次组件,提高性能
function TodoList() {
  const [list, setList] = useState(['学习 React'])

  const addItem = () => {
    setList([...list, '新的事项']) // 添加
  }

  const removeItem = (index: number) => {
    setList(list.filter((_, i) => i !== index)) // 删除
  }

  return (
    <div>
      <ul>
        {list.map((item, index) => (
          <li key={index}>
            {item}
            <button onClick={() => removeItem(index)}>删除</button>
          </li>
        ))}
      </ul>
      <button onClick={addItem}>添加事项</button>
    </div>
  )
}

表单处理与受控组件

  • 受控组件
    React 要求我们手动管理表单的值(不像 Vue 用 v-model):
    输入框的值受 useState 控制
    事件中用 setXxx() 更新值
  • 组件使用
表单控件受控写法
输入框value + onChange
复选框checked + onChange
单选框value + checked + onChange
下拉框value + onChange
//文本输入框(input[type=text])
function FormDemo() {
  const [name, setName] = useState('')
  return (
    <div>
      <input
        type="text"
        value={name}
        onChange={(e) => setName(e.target.value)}
        placeholder="请输入姓名"
      />
      <p>你好,{name}</p>
    </div>
  )
}

//复选框(checkbox)
const [isAgree, setIsAgree] = useState(false)

<input
  type="checkbox"
  checked={isAgree}
  onChange={(e) => setIsAgree(e.target.checked)}
/>
<span>我已阅读协议</span>

//单选框(radio)
const [gender, setGender] = useState('male')

<label>
  <input
    type="radio"
    value="male"
    checked={gender === 'male'}
    onChange={(e) => setGender(e.target.value)}
  /></label>

<label>
  <input
    type="radio"
    value="female"
    checked={gender === 'female'}
    onChange={(e) => setGender(e.target.value)}
  /></label>

//下拉框(select)
const [city, setCity] = useState('beijing')

<select value={city} onChange={(e) => setCity(e.target.value)}>
  <option value="beijing">北京</option>
  <option value="shanghai">上海</option>
  <option value="shenzhen">深圳</option>
</select>

React Router v6 路由系统

npm install react-router-dom
  • 设置路由容器(BrowserRouter)
    ! 是 TypeScript 语法中的一种 非空断言(Non-null Assertion),它的意思是告诉 TypeScript:“我很确定这里不会是 null,你不用报错。”
//在 main.tsx 或入口文件包裹一层
import { BrowserRouter } from 'react-router-dom'
import ReactDOM from 'react-dom/client'
import App from './App'

ReactDOM.createRoot(document.getElementById('root')!).render(
  <BrowserRouter>
    <App />
  </BrowserRouter>
)
  • 定义路由表(Routes + Route)
//1. App.tsx 或 App.jsx 文件中写(小项目)
//在 main.tsx 或 index.tsx 中包裹 <BrowserRouter>
import { Routes, Route } from 'react-router-dom'
import Home from './pages/Home'
import About from './pages/About'

function App() {
  return (
    <Routes>
      <Route path="/" element={<Home />} />
      <Route path="/about" element={<About />} />
    </Routes>
  )
}
//2. 单独建一个 router/index.tsx 文件(大型项目推荐)
// 在App.tsx 中使用
  • 页面跳转
//使用 <Link /> 跳转(类似 Vue 的 <router-link>)
//用于“JSX模板”中跳转
import { Link } from 'react-router-dom'

function Navbar() {
  return (
    <nav>
      <Link to="/">首页</Link>
      <Link to="/about">关于我们</Link>
    </nav>
  )
}

export default Navbar


// 编程式跳转(useNavigate)用于“逻辑代码”中跳转
import { useNavigate } from 'react-router-dom'

function HomePage() {
  const navigate = useNavigate()

  const goToAbout = () => {
    navigate('/about')
  }

  return <button onClick={goToAbout}>跳转到关于页</button>
}
  • 动态路由 & 参数(URL Params)
<Route path="/user/:id" element={<User />} />

//在组件中获取参数:
import { useParams } from 'react-router-dom'
const { id } = useParams()
  • 嵌套路由(父子页面结构)
    作用:页面布局复用、保持父结构不变,仅替换中间区域
    类似于Tab 页切换,父组件保持不变(比如顶部标题、导航栏、外层布局),子组件根据路径切换(比如内容区域变化)
<Route path="/dashboard" element={<Dashboard />}>
  <Route path="profile" element={<Profile />} />
  <Route path="settings" element={<Settings />} />
</Route>

//子组件用 <Outlet /> 占位
import { Outlet } from 'react-router-dom'//出口

export default function Dashboard() {
  return (
    <div>
      <h1>仪表盘</h1>
      <Outlet />//Outlet 就是“内容切换区域” 嵌套页面的渲染出口
    </div>
  )
}
  • 导航守卫模拟(useEffect + useNavigate + localStorage)
    比如没登录的就要跳转到登录页
// 在 Layout 或根组件中
import { useEffect } from 'react'
import { useLocation, useNavigate } from 'react-router-dom'

export default function Layout() {
  const location = useLocation()
  const navigate = useNavigate()

  useEffect(() => {
    const token = localStorage.getItem('token')
    if (!token && location.pathname !== '/login') {
      navigate('/login') // 模拟“导航守卫”
    }
  }, [location.pathname])
//第二个参数是依赖数组(dependency array) 根据其变化才响应执行useEffect函数
  return (
    <div>
      {/* 页面内容 */}
      <Outlet />
    </div>
  )
}

全局状态管理(Redux Toolkit vs Zustand)

两种主流方案:Redux Toolkit(企业级)、Zustand(轻量化)

  • 为什么需要全局状态?
    在以下情况中,你就该用全局状态:
    跨组件共享数据(如:用户登录信息、购物车、权限等)
    页面刷新保持状态(结合 localStorage)
    避免 props 一层层传递
  • 对比
项目Redux ToolkitZustand
学习成本中等(函数多)极低(像写普通 JS)
推荐场景企业级、大型项目中小项目、轻型应用
TS 支持✅ 非常好✅ 很好
DevTools✅(需中间件配置)✅ 内置支持

Redux Toolkit

npm install @reduxjs/toolkit react-redux
概念类比解释
state仓库的数据比如:当前用户是谁、是否登录
reducer管理员只能通过它修改数据
action修改请求单要写明“修改类型”和“修改内容”
dispatch(action)把请求单交给管理员派发请求,触发状态更新
  • reducer 和reducers
    reducer:一个函数,合并所有 reducers 的功能,它会接收当前的 state 和 action,然后返回新的 state。用于 替代 store 中的 reducer 函数。
    reducers:通常在 createSlice 或其他地方用于简化代码结构。是 Redux Toolkit 特有的概念,它是一个对象。包含多个处理不同状态更新的函数。
    • 为什么 export default userSlice.reducer,而不是 reducers
      createSlice 自动生成的reducer,在 Redux store 中使用的应该是合成后的 reducer 函数,而不是单个的 reducers 对象。
      reducer 函数:是createSlice 自动从 reducers 对象中派生出来的单一函数,它会负责合并所有的 reducer 函数,并且自动处理 state 的更新,返回更新后的状态。
      userSlice.reducers:包含了 login 和 logout 等多个 reducer 函数,每个函数负责一个特定的状态更新。
      userSlice.reducer:是一个合成后的 reducer 函数,实际上是 userSlice.reducers 对象的默认合并版本。
  • 创建状态模块(slice)
名称作用示例
reducers定义状态如何被修改login(state, action)
actions自动生成的 action 创建器函数login({name: '张三'})
reducer是最终导出的 reducer 函数export default userSlice.reducer
// store/userSlice.ts
import { createSlice } from '@reduxjs/toolkit'

const userSlice = createSlice({
  name: 'user',
  initialState: { name: '游客', isLogin: false },
  reducers: {
    login(state, action) {
      state.name = action.payload.name
      state.isLogin = true
    },
    logout(state) {
      state.name = '游客'
      state.isLogin = false
    },
    //Redux Toolkit 允许你“修改” state,因为内部使用了 immer 库处理不可变数据。
  },
})

export const { login, logout } = userSlice.actions
//Redux Toolkit 确实自动生成了 actions,
//但如果你在组件或外部文件里想用这些 action,
//必须手动 export 出来才能用。
export default userSlice.reducer
  • 配置 store
// store/index.ts
import { configureStore } from '@reduxjs/toolkit'
import userReducer from './userSlice'

const store = configureStore({
  reducer: {
    user: userReducer,
  },
})
/*
总目的:获取 Redux store 的根状态类型(RootState),自动推导类型,保证类型安全

store.getState 是 Redux store 提供的一个方法,
用来获取当前 Redux store 中的整个状态。
它会返回一个包含所有 reducer 状态的对象。

ReturnType<T> 是 TypeScript 提供的一个工具类型,它可以提取一个函数类型 T 的返回值类型。

在这个例子中,T 就是 typeof store.getState,
它返回的是 store.getState 函数的返回值类型,也就是 RootState。
*/
export type RootState = ReturnType<typeof store.getState>
export default store
  • 全局挂载 store(入口文件)
import { Provider } from 'react-redux'
import store from './store'

ReactDOM.createRoot(document.getElementById('root')!).render(
  <Provider store={store}>
    <App />
  </Provider>
)
  • 组件中使用状态(useSelector + useDispatch)
    useSelector:Redux 提供的 Hook,用于从全局 store 中读取数据。
    useDispatch:用于派发 action,触发 reducer 改变状态。
    RootState 是整个 Redux store 状态的类型(一般由 ReturnType
import { useSelector, useDispatch } from 'react-redux'
import { RootState } from '../store'
import { login, logout } from '../store/userSlice'
//从 userSlice 模块中导入 login 和 logout 这两个 action creator。

function UserInfo() {//组件定义
  const user = useSelector((state: RootState) => state.user)//读取状态
  const dispatch = useDispatch()
  //获取 Redux 的 dispatch 方法,用来派发 action

  return (
    <div>
      <p>用户名:{user.name}</p>
      {user.isLogin ? (
        <button onClick={() => dispatch(logout())}>退出</button>
      ) : (
        <button onClick={() => dispatch(login({ name: '张三' }))}>登录</button>
      )}
    </div>
  )
}

Zustand

npm install zustand
  • 创建状态
// store/useUserStore.ts
import { create } from 'zustand'

export const useUserStore = create((set) => ({
  name: '游客',
  isLogin: false,
  login: (name: string) => set({ name, isLogin: true }),
  logout: () => set({ name: '游客', isLogin: false }),
}))
  • 使用状态
import { useUserStore } from '../store/useUserStore'
function UserInfo() {
  const { name, isLogin, login, logout } = useUserStore()

  return (
    <div>
      <p>用户名:{name}</p>
      {isLogin ? (
        <button onClick={logout}>退出</button>
      ) : (
        <button onClick={() => login('李四')}>登录</button>
      )}
    </div>
  )
}

项目架构实战(Axios、鉴权、路由拦截)

  • Axios
npm install axios

支持拦截器

// utils/request.ts
import axios from 'axios'

const request = axios.create({
  baseURL: 'https://api.example.com',
  timeout: 5000,
})

// 请求拦截器:自动添加 token
request.interceptors.request.use((config) => {
  const token = localStorage.getItem('token')
  if (token) config.headers.Authorization = `Bearer ${token}`
  return config
})

// 响应拦截器:处理错误统一提示
request.interceptors.response.use(
  (res) => res.data,
  (err) => {
    alert('请求出错:' + err.response?.data?.message || err.message)
    return Promise.reject(err)
  }
)
//可选链操作符(Optional Chaining)  ES2020 的语法
//一层一层的去看其属性是否存在
export default request

// api/user.ts
import request from '../utils/request'

export function loginApi(data: { username: string; password: string }) {
  return request.post('/login', data)
}

export function getUserInfo() {
  return request.get('/user/info')
}
  • 登录鉴权:保存 Token + 用户信息
//登录成功后保存 token
const onLogin = async () => {
  const res = await loginApi({ username, password })
  localStorage.setItem('token', res.token)
  navigate('/dashboard')
}

//获取用户信息(全局状态)
const res = await getUserInfo()
const setUser = useUserStore((state) => state.setUser)
setUser(res.data) // 存入 Zustand / Redux

const dispatch = useDispatch()
dispatch(setUser(res.data)) // 存入 Redux 状态

//Zustand里面这么写的
import { create } from 'zustand'
const useUserStore = create((set) => ({
  user: null,
  setUser: (data) => set({ user: data })
}))

//Redux Toolkit则这么写
const userSlice = createSlice({
  name: 'user',
  initialState: { user: null },
  reducers: {
    setUser(state, action) {
      state.user = action.payload
    }
  }
})
export const { setUser } = userSlice.actions
  • 路由守卫(拦截未登录)
    React 没有 vue-router 的 beforeEach,推荐用“高阶组件”实现权限判断。
//创建一个权限路由组件
// components/AuthRoute.tsx
import { Navigate } from 'react-router-dom'
export default function AuthRoute({ children }: { children: JSX.Element }) {
  const token = localStorage.getItem('token')
  return token ? children : <Navigate to="/login" />
}

//使用
<Route
  path="/dashboard"
  element={
    <AuthRoute>
      <Dashboard />
    </AuthRoute>
  }
/>

Tailwind CSS + 动态样式 + 组件封装

  • 定义
    原子 CSS 工具 Tailwind,用于快速构建响应式、可维护的美观界面。通过类名来应用样式,而不需要写自定义的 CSS。
  • 安装
npm init -y #创建一个项目

npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
# 还可通过CDN引入 这种方法适合小项目

# 创建配置文件
npx tailwindcss init

创建一个 tailwind.config.js 文件和 postcss.config.js 文件。
可以自定义 Tailwind 的配置文件,调整颜色、间距、字体等。你可以在 tailwind.config.js 文件中进行配置。

//配置 tailwind.config.js
/** @type {import('tailwindcss').Config} 
这个注释作用:typescript类型声明、自动补全提示*/

export default {
  content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'],
  theme: {
    extend: {
      colors: {
        brand: '#3490dc',
      },/*使用 bg-brand 来设置背景色为你自定义的 #3490dc*/
    },
  },
  plugins: [],
}

在项目中创建一个 CSS 文件(如 styles.css),然后导入 Tailwind 的基本样式

/* styles.css */
@tailwind base;
@tailwind components;
@tailwind utilities;

/* 在 main.tsx 中引入*/
import './index.css'

配置构建工具,将 Tailwind 转换成最终的 CSS 文件(你可以使用工具如 PostCSS 或 Vite 来处理这一步)。
PostCSS 配置:适用于传统的构建工具,可以细粒度控制构建过程,适合需要自定义构建配置的项目。
Vite 配置:更现代化,具有极高的构建性能,尤其适用于前端项目,自动处理 CSS 并支持热重载。

使用 PostCSS 配置 Tailwind->CSS【不推荐】

PostCSS 是一个强大的工具,支持插件化的 CSS 处理。通过 PostCSS,你可以在构建过程中将 Tailwind 样式转化成最终的 CSS 文件。
注意:现代根本不需要单独用PostCSS单独构建,而是:把 Tailwind + PostCSS 集成到构建工具(如 Vite、Webpack、Next.js、Nuxt、Parcel 等)里自动处理。

npm init -y  # 初始化项目
npm install tailwindcss postcss autoprefixer
npx tailwindcss init  # 生成 tailwind.config.js

创建配置文件:生成 Tailwind 和 PostCSS 的配置文件

// postcss.config.js
module.exports = {
  plugins: [
    require('tailwindcss'),
    require('autoprefixer'),  // 自动添加前缀
  ],
};

创建 Tailwind 的入口文件:在项目中创建一个 CSS 文件(如 src/styles/tailwind.css),并在其中引入 Tailwind 的基础样式:

/* src/styles/tailwind.css */
@tailwind base;
@tailwind components;
@tailwind utilities;

在 package.json 中配置一个构建脚本,利用 PostCSS 来处理这个 CSS 文件,生成最终的 CSS 输出文件。

// package.json里添加
"scripts": {
  "build": "postcss src/styles/tailwind.css -o dist/styles.css"
}

执行构建:运行以下命令,PostCSS 会处理 Tailwind CSS 文件并生成最终的 styles.css 文件。构建后的 dist/styles.css 文件会包含 Tailwind 样式,最终你可以将它链接到你的 HTML 文件中。

npm run build

使用 Vite 配置 Tailwind->CSS

Vite 是一个现代化的构建工具,它具有很好的性能,并且支持 Tailwind CSS 配置得非常简单。
使用 Vite,其实已经默认内置了 PostCSS 支持,你只要正常安装 Tailwind 并配置它,它会自动通过 PostCSS 插件系统来处理,无需你手动搭配。但如果你想更明确地控制 PostCSS 的行为,也可以显式地配置它。

npm init vite@latest my-project
cd my-project
npm install
npm install tailwindcss postcss autoprefixer
npx tailwindcss init

初始化 Tailwind 配置,配置 tailwind.config.js

// tailwind.config.js
module.exports = {
  content: [
    "./index.html",
    "./src/**/*.{js,ts,jsx,tsx}", // 这里指定你的 HTML 或 JavaScript 文件位置
  ],
  theme: {
    extend: {},
  },
  plugins: [],
};

创建 Tailwind 的入口文件 并引入其样式

/* src/assets/styles/tailwind.css */
@tailwind base;
@tailwind components;
@tailwind utilities;

一般只需要在 JavaScript 入口文件(比如 main.js 或 main.ts)中引入样式即可。
import './index.css'; // 假设你的 Tailwind CSS 入口文件是 index.css,引入到js 就相当于引入到关联它的html中了

<!-- index.html 引入样式
不需要手动在 HTML 中引入 CSS 文件
-->
<head>
  <link rel="stylesheet" href="/src/assets/styles/tailwind.css">
</head>

使用 Vite 启动开发服务器,在浏览器中实时查看 Tailwind 样式的效果。Vite 会自动处理 CSS 文件,包括 Tailwind 的转换过程,并在浏览器中即时显示结果。

npm run dev #热重载、即时更新
npm run build #生产环境打包

使用

  • 常用类名
类别类名描述
布局container设置元素为响应式容器
flex设置元素为 flexbox 布局容器
grid设置元素为网格布局容器
block设置元素为块级元素
inline设置元素为行内元素
justify-center水平居中对齐(flex 或 grid 布局中)
items-center垂直居中对齐(flex 布局中)
space-x-{size}设置元素之间的水平间距
space-y-{size}设置元素之间的垂直间距
尺寸w-{size}设置宽度,如 w-1/2, w-full
h-{size}设置高度,如 h-12, h-full
max-w-{size}设置最大宽度
min-h-screen设置最小高度为整个屏幕的高度
间距m-{size}设置外边距(四个方向)
p-{size}设置内边距(四个方向)
mt-{size}设置上外边距
mb-{size}设置下外边距
pl-{size}设置左内边距
pr-{size}设置右内边距
字体text-{color}设置文字颜色,如 text-red-500
font-{weight}设置字体粗细,如 font-bold, font-light
text-{size}设置字体大小,如 text-xl, text-2xl
leading-{size}设置行高
tracking-{size}设置字间距
背景bg-{color}设置背景颜色,如 bg-blue-500
bg-cover设置背景图片完全覆盖元素
bg-center设置背景图片居中显示
边框border添加边框
border-{color}设置边框颜色
border-{size}设置边框宽度,如 border-2
rounded添加圆角,如 rounded-lg
border-t只设置上边框
响应式设计sm:{class}在屏幕宽度大于等于 640px 时应用该样式
md:{class}在屏幕宽度大于等于 768px 时应用该样式
lg:{class}在屏幕宽度大于等于 1024px 时应用该样式
xl:{class}在屏幕宽度大于等于 1280px 时应用该样式
其他常用类opacity-{value}设置元素透明度,如 opacity-50
shadow添加阴影,如 shadow-lg
overflow-hidden隐藏超出元素边界的内容
z-{index}设置元素的 z-index
状态类hover:{class}悬停时应用的类,如 hover:bg-blue-500
focus:{class}聚焦时应用的类,如 focus:ring-2
active:{class}按下时应用的类,如 active:bg-red-500
disabled设置元素为禁用状态(用于表单元素或按钮等)
过渡和动画transition添加过渡效果,如 transition-all
duration-{time}设置过渡动画的持续时间,如 duration-300
ease-{timing}设置过渡动画的节奏函数,如 ease-in-out
transform启用 CSS 变换(如旋转、缩放)
scale-{value}设置元素缩放,如 scale-110
rotate-{deg}设置元素旋转角度,如 rotate-45

在 Vue 或 React 中,动态样式是指根据变量、状态、条件等来动态控制元素的样式。

用户权限系统设计(角色控制、按钮权限、菜单权限)

类型示例
页面权限未登录不能访问 /admin,普通用户不能访问 /setting
菜单权限普通用户菜单只有“首页”和“个人中心”,管理员菜单有更多功能
按钮权限有“编辑权限”的用户才能看到“编辑按钮”
  • 设置权限模型(角色 + 权限码)
//登陆接口res:
{
  user: {
    name: '张三',
    role: 'admin',
    permissions: ['user:add', 'user:edit', 'menu:view']
  }
}
//保存权限数据(Zustand 示例)
// store/useAuthStore.ts
import { create } from 'zustand'

export const useAuthStore = create((set) => ({
  role: '', // 'admin' | 'user'
  permissions: [] as string[],//初始值是一个空数组 且 只能放string类型元素
  setAuth: (data: { role: string; permissions: string[] }) =>
    set(data),
}))
//路由权限控制 带角色检查的路由守卫
import { useAuthStore } from '../store/useAuthStore'
import { Navigate } from 'react-router-dom'

export default function RoleRoute({
  children,
  allowedRoles,
}: {
  children: JSX.Element
  allowedRoles: string[]
}) {
  const { role } = useAuthStore()
  return allowedRoles.includes(role) ? children : <Navigate to="/403" />
}

<Route
  path="/admin"
  element={
    <RoleRoute allowedRoles={['admin']}>
      <AdminPage />
    </RoleRoute>
  }
/>

//菜单权限控制(动态渲染)
const allMenus = [
  { name: '首页', path: '/', code: 'home:view' },
  { name: '用户管理', path: '/users', code: 'user:view' },
]

function MenuList() {
  const { permissions } = useAuthStore()
  const visibleMenus = allMenus.filter((m) =>
    permissions.includes(m.code)
  )

  return (
    <ul>
      {visibleMenus.map((m) => (
        <li key={m.path}>
          <Link to={m.path}>{m.name}</Link>
        </li>
      ))}
    </ul>
  )
}

//按钮权限控制(最常见) 没权限时不可见
function DeleteButton() {
  const { permissions } = useAuthStore()
  if (!permissions.includes('user:delete')) return null

  return (
    <button className="bg-red-500 text-white px-2 py-1 rounded">
      删除用户
    </button>
  )
}

性能优化与引用管理(useRef / useMemo / useCallback)

  • useRef
    主要用于持有对 DOM 元素的引用,或者存储某些需要在组件重新渲染时保留的值。
  • useMemo
    用于性能优化,可以缓存值,避免不必要的重新计算。
  • useCallback
    用于缓存函数,避免在每次渲染时重新创建函数。
const inputRef = useRef<HTMLInputElement>(null)//初始值null
const focusInput = () => {
  inputRef.current?.focus()
/*
?. 是可选链操作符,意味着如果 inputRef.current 不是 null,才会执行 focus()
如果 inputRef.current 是 null,则什么也不做,避免发生错误。
*/
}
return <input ref={inputRef} />
/*
这段代码的意思是:执行focusInput函数可以在任何时候将焦点设置到引用的这个input上
*/

const expensiveComputation = useMemo(() => {
  return heavyCalculation(value)
}, [value]) //[value] 是 依赖数组

const memoizedCallback = useCallback(() => {
  // 执行某些操作
}, [dependencies])

自定义 Hooks

提炼逻辑,提高复用性

  • hooks定义及作用
    在 Hooks 出现之前,你想在组件中使用“状态”或“生命周期方法”(如 componentDidMount)只能用 class 组件 写法。 class 太重、不易复用、逻辑混乱,所以 React 团队就发明了 Hooks。
    函数组件 + Hooks 的写法,简单清爽。React Hooks 让你能在不写 class 的情况下使用状态、生命周期、DOM 引用、性能优化等功能。
//无hooks
class MyComponent extends React.Component {
  state = { count: 0 }

  componentDidMount() {
    console.log('组件挂载了');
  }

  render() {
    return <div>{this.state.count}</div>;
  }
}
//有hooks
import { useState, useEffect } from 'react';

function MyComponent() {
  const [count, setCount] = useState(0); // 状态

  useEffect(() => {
    console.log('组件挂载了'); // 生命周期
  }, []);

  return <div>{count}</div>;
}

  • 常见的hooks
Hook作用
useState添加本地状态(替代 class 的 this.state
useEffect副作用处理,如生命周期函数、数据请求等(替代 componentDidMount/DidUpdate/WillUnmount
useRef获取 DOM 引用或存储可变值(不触发更新)
useContext跨组件共享全局数据(状态管理)
useMemo结果缓存,优化性能
useCallback函数缓存,避免不必要的重渲染
useReducer复杂状态管理(类似 Redux)
//自定义 useFetch Hook
function useFetch(url: string) {
  const [data, setData] = useState(null)
  const [loading, setLoading] = useState(true)

  useEffect(() => {
    const fetchData = async () => {
      const response = await fetch(url)
      const result = await response.json()
      setData(result)
      setLoading(false)
    }

    fetchData()//调用
  }, [url])//依赖url

  return { data, loading }
}

Redux 异步与中间件 (createAsyncThunk、logger )

  • createAsyncThunk
    用于创建异步操作,结合 Redux 来处理 API 请求。
    • 有什么用?对比直接用fetch+hooks
      中大型项目使用,统一管理复杂异步逻辑、状态、错误处理,更可维护、更清晰、更好调试。
功能
自动创建三种状态(pending / fulfilled / rejected)
自动处理 loading / error / data
支持中间件(日志、调试工具)
多组件共享请求状态
与 Redux DevTools 配合追踪异步流程
可以复用请求逻辑
单元测试更方便
// store/userSlice.ts
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit'

export const fetchUser = createAsyncThunk(
  'user/fetchUser',
  async (userId: string) => {
    const response = await fetch(`/api/user/${userId}`)
    return response.json()
  }
)

// 定义异步 action
export const fetchUser = createAsyncThunk('user/fetch', async (id: string) => {
  const response = await fetch(`/api/user/${id}`);
  return await response.json();
});

// 在 slice 中响应状态
const userSlice = createSlice({
  name: 'user',
  initialState: { data: null, loading: false, error: null },
  reducers: {},
  extraReducers: (builder) => {
    builder
      .addCase(fetchUser.pending, (state) => {
        state.loading = true;
      })
      .addCase(fetchUser.fulfilled, (state, action) => {
        state.loading = false;
        state.data = action.payload;
      })
      .addCase(fetchUser.rejected, (state, action) => {
        state.loading = false;
        state.error = action.error.message;
      });
  },
});
  • logger 中间件
    logger 是一个 Redux 中间件,它的作用是:便于调试
    在每次 action 被派发(dispatch)时,自动在控制台打印出:
    当前的状态(state)
    你派发的 action 是什么
    派发后的新状态(next state)
    注意:logger 只建议在 开发环境 使用,生产环境会影响性能和暴露数据。
//一般写在:src/app/store.ts 文件中
import { applyMiddleware } from 'redux'
import logger from 'redux-logger'

const store = configureStore({
  reducer: rootReducer,
  middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(logger),
})
//还需要在 main.tsx(或 index.tsx)里引入这个 store,并注入给应用
// src/main.tsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import { Provider } from 'react-redux';
import store from './app/store'; // 👈 引入刚才配置的 store

ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <Provider store={store}> {/* 👈 用 Provider 注入 */}
      <App />
    </Provider>
  </React.StrictMode>
);

项目架构设计 (文件结构、目录规范、alias 设置)

src/
├── assets/            // 静态资源
├── components/        // 共享组件
├── features/          // 功能模块(User、Product)
├── hooks/             // 自定义 Hooks
├── store/             // Redux 或 Zustand 状态管理
├── styles/            // 样式文件(CSS、SCSS)
├── pages/             // 页面模块
└── utils/             // 工具函数、API
  • 配置 alias(Vite 配置)
    为什么要配置它?简化路径、便于维护
// vite.config.ts
import { defineConfig } from 'vite'
import path from 'path'

export default defineConfig({
  resolve: {
    alias: {
      '@components': path.resolve(__dirname, 'src/components'),
      '@hooks': path.resolve(__dirname, 'src/hooks'),
    },
  },
})

样式系统

Tailwind CSS、CSS Modules【不推荐】、shadcn/ui 组件库

  • shadcn/ui 是基于 Tailwind CSS 构建的 UI 组件库,可以快速集成到你的项目中。

项目打包部署 + Vite 构建优化上线

  • Vite 基础配置
//package.json 
"scripts": {
  "dev": "vite",
  "build": "vite build",
  "preview": "vite preview"
}

npm run build 
//生成 dist/ 文件夹,包含打包好的 index.html + assets 静态资源。
  • 多环境变量配置(env)
#在根目录添加环境文件
.env                  # 默认开发环境
.env.development	#仅开发环境生效(vite dev)
.env.production       # 生产环境(vite build)
.env.staging          # 测试环境

#每个文件中定义变量必须以 VITE_ 开头:
# .env
VITE_API_BASE=http://localhost:3000/api

# .env.production
VITE_API_BASE=https://api.example.com

npm run dev       # 使用 .env.development
npm run build     # 使用 .env.production
// 在代码里使用
//所有变量都通过 import.meta.env 访问。
const baseURL = import.meta.env.VITE_API_BASE_URL;
console.log(baseURL);

if (import.meta.env.MODE === 'development') {
  console.log('这是开发环境');
}

//可以在 vite.config.ts 中也使用这些变量
export default defineConfig({
  base: process.env.VITE_BASE_URL || '/',
});
/*
base 属性 是用来指定你的应用程序在部署时的基础路径
设置了 base,Vite 会自动为静态资源加上这个前缀
*/
  • 环境变量有啥用?
  1. 不同环境请求不同的接口
  2. 动态设置页面标题 / 域名 / 图标等
  3. 控制功能开关(如是否开启调试日志)
  4. 配置第三方服务密钥(如 Firebase、Sentry 等)
  5. 如果直接用变量常量代替, 容易忘记修改、公用一个配置不安全、不能适配不同环境
// .env.development
VITE_API_URL=http://localhost:3000/api

// .env.production
VITE_API_URL=https://api.production.com

VITE_SITE_TITLE=我的博客

VITE_DEBUG=true

VITE_FIREBASE_KEY=xxx
VITE_SENTRY_DSN=xxx
axios.get(import.meta.env.VITE_API_URL + '/users');

document.title = import.meta.env.VITE_SITE_TITLE;

if (import.meta.env.VITE_DEBUG === 'true') {
  console.log('调试信息:xxxxx');
}
  • 构建优化配置(vite.config.ts)
    在 Vite 中,打包优化(如代码分包、压缩等)通常需要借助 插件 和 配置,尤其是借助 vite-plugin 和内建的 Rollup 配置。Vite 本身基于 Rollup 进行打包,因此它的优化过程与 Rollup 的优化机制紧密相关。
  1. 代码分包(Code Splitting)
    Vite 默认支持 代码分包,当你使用多个页面或动态导入模块时,Vite 会自动按需分包。 Vite 默认开启了 Rollup 的代码分割,可以直接在项目中使用,不需要额外配置。如果你的应用是多页面应用(MPA)或者使用了多个路由,Vite 会自动根据页面或路由拆分代码。
    异步组件: 使用 Vue 或 React 的异步组件,也会自动实现代码分割。
  2. 压缩优化(Code Minification)
    Vite 在生产模式下会自动启用 Terser 插件来压缩代码。这是一个用于 JavaScript 压缩的工具,可以帮助减小文件大小,提高加载速度。
    默认情况下,在 vite build 时,Vite 会自动使用 Terser 进行 JavaScript 压缩。如果你需要定制压缩行为,可以修改 vite.config.ts 中的 Rollup 配置。
// vite.config.ts
export default defineConfig({
  build: {
    terserOptions: {
      compress: {
        drop_console: true, // 去掉 console.log
      },
    },
  },
});
  1. 图片压缩和优化
    使用 Vite 插件对图片进行优化,比如 vite-plugin-imagemin,减少图片的大小,提升加载速度。
npm install vite-plugin-imagemin --save-dev

// vite.config.ts
import viteImagemin from 'vite-plugin-imagemin';

export default defineConfig({
  plugins: [
    viteImagemin({
      gifsicle: { optimizationLevel: 3 },
      optipng: { optimizationLevel: 7 },
      mozjpeg: { quality: 80 },
    }),
  ],
});

  1. CSS 优化(压缩、提取)
    Vite 会自动提取和压缩 CSS 文件。你可以进一步定制 CSS 优化
    CSS 提取: Vite 会默认提取所有的 CSS 到单独的文件中。
    CSS 压缩: 使用 cssnano 等工具进行进一步压缩。通过配置 postcss 插件实现。
// vite.config.ts
export default defineConfig({
  css: {
    postcss: {
      plugins: [
        require('cssnano')({ preset: 'default' }), // CSS 压缩
      ],
    },
  },
});
  1. 动态加载(Lazy Loading)和预加载(Preloading)
  2. 缓存优化(Cache)
    配置缓存策略来优化生产构建时的缓存行为,例如通过设置文件名哈希值来强制浏览器更新缓存
  3. 第三方插件进一步优化
    vite-plugin-pwa:可以将应用程序打包为 PWA(Progressive Web App),支持离线缓存。
    vite-plugin-compression:自动压缩构建后的文件(如 gzip、brotli)以减少网络传输时的体积。
import ViteCompression from 'vite-plugin-compression';

export default defineConfig({
  plugins: [ViteCompression()],
});
  1. Tree Shaking 和死代码消除(Dead Code Elimination)
    Vite 默认启用 Tree Shaking 和 Rollup 的死代码消除,这意味着未使用的代码不会被打包进最终构建中,进一步减少包的体积。
  • Nginx 本地部署
# 构建
npm run build

# 假设你已经安装了 nginx
# 拷贝 dist 文件夹到 nginx/html
cp -r dist/* /usr/share/nginx/html

#nginx.conf 配置
server {
  listen 80;
  server_name yourdomain.com;

  location / {
    root /usr/share/nginx/html;
    index index.html;
    try_files $uri $uri/ /index.html;
    #try_files $uri /index.html 是为了支持 React Router 前端路由
  }
}

进阶【后续更新】

表单系统构建 使用 React Hook Form + Yup 校验
React Query 入门 (请求缓存、分页、依赖请求、状态处理 )
动态加载 + 异步组件 (React.lazy、Suspense、代码拆分)
单元测试:Vitest、React Testing Library、覆盖率
国际化:i18next
动画:Framer Motion
微前端方案:Module Federation
SSR:Next.js 简介与迁移建议
多环境配置与部署优化 .env、Vite 插件、构建优化、CDN

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

七灵微

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值