react最核心的三件事:
- 组件(页面拆成一块块)
- 状态(useState)(数据变,页面自动变)
- Props(组件之间传值)
整体总结构
html
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配置
函数式组件(最常用的写法)
javascript
// 1. 定义组件
function Home() {
return (
<div>
<h1>你好,React</h1>
</div>
)
}
export default Home
useState状态(数据驱动页面)
数据变,页面自动刷新
javascript
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 父传子(组件传值)
javascript
//父组件:
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
javascript
function ButtonDemo() {
const handleClick = () => {
alert('你点我了')
}
return (
<button onClick={handleClick}>点击</button>
)
}
循环渲染列表
javascript
function List() {
const list = ['苹果', '香蕉', '橙子']
return (
<ul>
{list.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
)
}
条件判断(显示 / 隐藏)
javascript
function ShowHide() {
const [isShow, setIsShow] = useState(true)
return (
<div>
{isShow && <p>我显示出来了</p>}
<button onClick={() => setIsShow(!isShow)}>
切换显示/隐藏
</button>
</div>
)
}
表单输入绑定(input)
javascript
function InputDemo() {
const [value, setValue] = useState('')
return (
<div>
<input
value={value}
onChange={(e) => setValue(e.target.value)}
placeholder="请输入"
/>
<p>你输入的:{value}</p>
</div>
)
}
useEffect 副作用(请求数据、定时器)
javascript
//无依赖 → 组件每次渲染都执行
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 样式
javascript
function Box() {
return (
<div className="box-style">我是样式</div>
)
}
.box-style {
color: red;
font-size: 20px;
}
简单逻辑运算
javascript
function Demo() {
const age = 20
return (
<div>
{age >= 18 ? '成年' : '未成年'}
</div>
)
}
React通信
javascript
//父组件通过 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状态管理工具
安装
javascript
npm install zustand
新建 src/store/useUserStore.js
javascript
import { create } from 'zustand'
// 全局状态仓库
export const useUserStore = create((set) => ({
userName: '',
token: '',
// 修改状态方法
setUser: (name, token) => set({ userName: name, token }),
clearUser: () => set({ userName: '', token: '' })
}))
任意组件使用:
javascript
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>
)
}