react最核心的三件事:

  • 组件(页面拆成一块块)
  • 状态(useState)(数据变,页面自动变)
  • Props(组件之间传值)

整体总结构

react-big-project/
├── public/                # 静态资源入口(不被webpack编译)
├── src/
│   ├── api/               # 所有后端接口请求
│   ├── assets/            # 静态资源:图片、字体、全局样式、svg
│   ├── components/        # 公共通用组件 + 业务通用组件
│   ├── config/            # 全局配置、常量、环境变量
│   ├── hooks/             # 自定义全局Hooks
│   ├── layouts/           # 全局布局组件(侧边栏、顶部导航、主体布局)
│   ├── pages/             # 所有业务页面
│   ├── router/            # 路由配置、路由守卫、权限路由
│   ├── store/             # 全局状态管理
│   ├── styles/            # 全局公共样式、主题样式
│   ├── types/             # TS类型定义(TS项目专用)
│   ├── utils/             # 全局工具函数
│   ├── App.tsx            # 根组件
│   ├── main.tsx           # 项目入口
│   └── vite-env.d.ts      # Vite环境声明
├── .env                   # 开发环境变量
├── .env.production        # 生产环境变量
├── package.json
├── tsconfig.json          # TS配置
└── vite.config.ts         # Vite配置

函数式组件(最常用的写法)

// 1. 定义组件
function Home() {
  return (
    <div>
      <h1>你好,React</h1>
    </div>
  )
}

export default Home

useState状态(数据驱动页面)

数据变,页面自动刷新

import { useState } from 'react'

function Demo() {
  // 定义状态:变量名、修改变量的方法、默认值
  const [count, setCount] = useState(0)
  const [name, setName] = useState('张三')

  return (
    <div>
      <p>数字:{count}</p>
      <button onClick={() => setCount(count + 1)}>点我+1</button>

      <p>名字:{name}</p>
      <button onClick={() => setName('李四')}>改名字</button>
    </div>
  )
}

Props 父传子(组件传值)

//父组件:
import Child from './Child'

function Parent() {
  return (
    <div>
      <Child name="小明" age={18} />
    </div>
  )
}

//子组件:
function Child(props) {
  return (
    <div>
      <p>姓名:{props.name}</p>
      <p>年龄:{props.age}</p>
    </div>
  )
}

export default Child

点击事件onclick

function ButtonDemo() {
  const handleClick = () => {
    alert('你点我了')
  }

  return (
    <button onClick={handleClick}>点击</button>
  )
}

循环渲染列表

function List() {
  const list = ['苹果', '香蕉', '橙子']

  return (
    <ul>
      {list.map((item, index) => (
        <li key={index}>{item}</li>
      ))}
    </ul>
  )
}

条件判断(显示 / 隐藏)

function ShowHide() {
  const [isShow, setIsShow] = useState(true)

  return (
    <div>
      {isShow && <p>我显示出来了</p>}

      <button onClick={() => setIsShow(!isShow)}>
        切换显示/隐藏
      </button>
    </div>
  )
}

表单输入绑定(input)

function InputDemo() {
  const [value, setValue] = useState('')

  return (
    <div>
      <input
        value={value}
        onChange={(e) => setValue(e.target.value)}
        placeholder="请输入"
      />
      <p>你输入的:{value}</p>
    </div>
  )
}

useEffect 副作用(请求数据、定时器)

//无依赖 → 组件每次渲染都执行
useEffect(() => {
  console.log("组件每次渲染都会执行")
})

//空数组依赖 → 只在组件挂载时执行一次(最重要)
useEffect(() => {
  console.log("组件一上来就执行,只执行一次")
}, [])
//相当于 Vue 的 onMounted

// 带依赖 → 依赖变化时执行
useEffect(() => {
  console.log("count 变了就执行")
}, [count])

//常用写法
//组件一加载就发请求
import { useState, useEffect } from 'react'

function Demo() {
  const [list, setList] = useState([])

  // 组件一渲染就发请求
  useEffect(() => {
    async function getList() {
      let res = await fetch("https://api.xxx.com/list")
      let data = await res.json()
      setList(data)
    }
    
    getList()
  }, []) // 空数组 = 只执行一次

  return <div>{list.length}</div>
}

//监听某个值变化时执行
const [count, setCount] = useState(0)

useEffect(() => {
  console.log("count 变了:", count)
}, [count]) // 只有 count 变才执行

//清除副作用(定时器,订阅)
useEffect(() => {
  let timer = setInterval(() => {
    console.log("每秒执行")
  }, 1000)

  // 返回清理函数
  return () => {
    clearInterval(timer) // 组件销毁时清除定时器
  }
}, [])

React内部有一条规则:
在一个effect即将被销毁或重新执行之前,如果上一次effect有返回一个函数,就调用它。
组件卸载时:会找到这个组件上存储的“需要清理的函数",然后调用它。
依赖变化导致effect重新执行之前:也会先调用上一次返回的清理函数。

className 样式

function Box() {
  return (
    <div className="box-style">我是样式</div>
  )
}


.box-style {
  color: red;
  font-size: 20px;
}

简单逻辑运算

function Demo() {
  const age = 20

  return (
    <div>
      {age >= 18 ? '成年' : '未成年'}
    </div>
  )
}

React通信

//父组件通过 props 传给子组件
//父组件
function Parent() {
  return <Child name="张三" age={20} />
}
//子组件
function Child(props) {
  return <div>{props.name},{props.age}</div>
}

//子调用父传过来的函数,把数据传给父
//父组件
function Parent() {
  const getChildData = (data) => {
    console.log("子组件传过来的数据:", data)
  }

  return <Child onGetData={getChildData} />
}
//子组件
function Child({ onGetData }) {
  const send = () => {
    onGetData("我是子组件数据")
  }

  return <button onClick={send}>传给父组件</button>
}
//一句话:子传父 = 父传函数,子调用函数

//跨多层组件通信(爷孙,深层)
//创建上下文
import { createContext } from 'react'
export const MyContext = createContext()
//顶层提供数据
import { MyContext } from './xxx'

function Grand() {
  return (
    <MyContext.Provider value={{ name: "张三" }}>
      <Parent />
    </MyContext.Provider>
  )
}
//后代组件使用数据
import { useContext } from 'react'
import { MyContext } from './xxx'

function Child() {
  const ctx = useContext(MyContext)
  return <div>{ctx.name}</div>
}

Zustand状态管理工具

安装

npm install zustand

新建 src/store/useUserStore.js

import { create } from 'zustand'

// 全局状态仓库
export const useUserStore = create((set) => ({
  userName: '',
  token: '',
  // 修改状态方法
  setUser: (name, token) => set({ userName: name, token }),
  clearUser: () => set({ userName: '', token: '' })
}))

任意组件使用:

import { useUserStore } from '@/store/useUserStore'

function Demo() {
  // 取值
  const userName = useUserStore(state => state.userName);
  // 改值
  const setUser = useUserStore(state => state.setUser);

  return (
    <div>
      <p>用户名:{userName}</p>
      <button onClick={() => setUser('张三', 'abc123')}>设置用户</button>
    </div>
  )
}

React项目路由react-router-dom

//1. 新建路由文件 src/router/index.jsx
import { createBrowserRouter, RouterProvider } from 'react-router-dom';
import Home from '../views/Home';
import About from '../views/About';
import NotFound from '../views/NotFound';

// 配置路由表
const router = createBrowserRouter([
  {
    path: '/',
    element: <Home />
  },
  {
    path: '/about',
    element: <About />
  },
  {
    path: '*', // 404
    element: <NotFound />
  }
]);

// 导出路由
export default router;

//2. 在 main.jsx 入口引入
import React from 'react';
import ReactDOM from 'react-dom/client';
import { RouterProvider } from 'react-router-dom';
import router from './router';

ReactDOM.createRoot(document.getElementById('root')).render(
  <React.StrictMode>
    {/* 挂载路由 */}
    <RouterProvider router={router} />
  </React.StrictMode>
);

//3. 页面跳转(组件中)
import { Link } from 'react-router-dom';

function Nav() {
  return (
    <div>
      <Link to="/">首页</Link>
      <Link to="/about">关于</Link>
    </div>
  );
}

//import { useNavigate } from 'react-router-dom';

function Login() {
  const navigate = useNavigate();

  const goHome = () => {
    // 跳转页面
    navigate('/');
    // 返回上一页
    // navigate(-1);
  };

  return <button onClick={goHome}>去首页</button>;
}

更多推荐