前言
这是本人在学习React时记的一些笔记,利用大模型进行了一些整理,希望能够有所帮助。目前笔记还是不完整版本,后续还会继续补充更新。
React基础
1. 核心概念
-
React:用于构建 Web 和原生交互界面的库,非框架(对比 Vue)
-
核心特性:组件化开发、高效的虚拟 DOM diff 算法、跨平台支持(React Native)
-
生态组成:基础篇、Redux 状态管理、Router 路由、实战项目、TypeScript 拓展等
2. 开发环境搭建
-
工具:create-react-app(基于 Webpack,开箱即用)
-
命令:
npx create-react-app [项目名称] # 示例:npx create-react-app react-basic
-
npx:Node.js 工具命令,执行包命令
-
create-react-app:核心包,固定写法
-
[项目名称]:自定义项目名
3. JSX 语法
-
定义:JavaScript 与 XML(HTML)的混合语法,用于编写 UI 模板
-
示例:
const message = 'this is message';function App() { return ( <div> <h1>this is title</h1> {message} {/* 嵌入JS表达式 */} </div> );}
-
特性:
-
声明式模板(类似 HTML)+ 可编程能力(JS 逻辑)
-
需 Babel 转码后浏览器才能解析
-
表达式规则:
-
支持变量、函数调用、对象等表达式(用{}包裹)
-
不支持:if/switch语句、变量声明(需用三元表达式或自定义函数替代)
4. 条件渲染与列表渲染
-
条件渲染:
-
简单场景:逻辑与运算符(&&)、三元表达式(?:)
{flag && <span>显示内容</span>}{loading ? <span>加载中...</span> : <span>加载完成</span>}
- 复杂场景:自定义函数结合if判断
const articleType = 2;function getArticleTemp() { if (articleType === 0) return <div>JAVA天下第一</div>; else if (articleType === 1) return <div>Python天下第一</div>; else return <div>C++天下第一</div>;}{getArticleTemp()}
- 列表渲染:
const list = [{id:1,name:'liangliang'}, {id:2,name:'kiana'}];<ul> {list.map(item => <li key={item.id}>{item.name}</li>)} {/* key为必选属性,用于diff优化 */}</ul>
5. 事件绑定
-
语法:on+事件名(驼峰命名),绑定函数引用
-
基础用法:
function App() { const clickHandler = () => console.log('按钮点击'); return <button onClick={clickHandler}>点击我</button>;}
-
传递参数:
-
自定义参数:通过箭头函数包裹
<button onClick={() => clickHandler('jack')}>点击</button>
- 同时传递事件对象和参数:
<button onClick={(e) => clickHandler('jack', e)}>点击</button>
- 注意:避免直接写函数调用(如onClick={clickHandler()}),需传递函数引用
组件开发
1. 组件基础
-
定义:首字母大写的函数,返回 JSX 结构
-
示例:
// 定义组件
function Button() {
return <button>Click me</button>;
}
// 使用组件
function App() {
return (
<div>
<Button /> {/* 自闭合标签 */}
<Button></Button> {/* 成对标签 */}
</div>
);
}
- 组件化优势:复用性高、可嵌套、逻辑与视图分离
2. 状态管理(useState)
-
作用:为函数组件添加状态变量,数据驱动视图更新
-
基础用法:
const [count, setCount] = useState(0); // 初始值为0<button onClick={() => setCount(count + 1)}>{count}</button>
-
特性:
-
状态不可变:需通过setState更新状态,直接修改无效
// 错误:直接修改状态不触发更新
count++;
// 正确:通过set函数更新
setCount(prev => prev + 1);
- 对象 / 数组状态:需返回全新对象 / 数组
const [form, setForm] = useState({ name: 'jack' });setForm({ ...form, name: 'john' }); // 用展开运算符创建新对象
3. 组件通信
- 父传子(Props):
// 父组件
<Son name="App数据" age={20} />
// 子组件
function Son({ name, age }) { return <div>{name}, {age}</div>; }
-
父组件在子组件标签上绑定属性,子组件通过props接收
-
Props 特性:可传递任意类型数据(包括函数、JSX),且为只读
-
子传父:
// 父组件
function App() {
const handleMsg = (msg) => console.log(msg);
return <Son onMsg={handleMsg} />;
}
// 子组件
function Son({ onMsg }) {
const sendMsg = () => onMsg('子组件消息');
return <button onClick={sendMsg}>发送消息</button>;
}
-
父组件传递回调函数给子组件,子组件调用时传递数据
-
跨层级通信(Context):
const Context = createContext(); // 创建上下文
<Context.Provider value="全局数据">// 顶层组件
<ChildComponent /></Context.Provider>// 底层组件
function ChildComponent() {
const data = useContext(Context); // 直接获取数据
return <div>{data}</div>;}
- 创建上下文对象,顶层组件提供数据,底层组件直接消费
4. 生命周期与副作用(useEffect)
-
作用:处理副作用操作(如 AJAX 请求、DOM 操作、定时器等)
-
语法:
useEffect(() => {
// 副作用逻辑(如获取数据)
async function fetchData() { ... } fetchData();
// 清除副作用(返回函数,组件卸载时执行)
return () => { clearInterval(timer); };
}, [依赖项]);// 依赖项变化时重新执行,空数组表示仅初始渲染时执行一次
- 示例:组件挂载时获取数据
useEffect(() => { fetch('http://api.channels') .then(res => res.json()) .then(data => setChannels(data));}, []); // 仅初始渲染时执行
高级特性
1. 自定义 Hook
-
作用:复用组件逻辑(如状态切换、数据请求)
-
示例:封装布尔值切换 Hook
function useToggle(initialValue = true) {
const [value, setValue] = useState(initialValue);
const toggle = () => setValue(!value);
return { value, toggle }; // 返回状态和方法
}
//使用
function App() {
const { value, toggle } = useToggle();
return ( <div> {value ? <div>显示内容</div> : null}
<button onClick={toggle}>切换</button> </div> );}
-
规则:
-
函数名必须以use开头
-
只能在组件或其他 Hook 中调用,且位于顶层(非嵌套在if/ 循环中)
2. Redux 状态管理
-
作用:集中管理应用状态(类似 Vue 的 Pinia),适用于复杂应用
-
核心概念:
-
State:存储应用状态的对象
-
Action:描述状态变更的对象(如{ type: ‘increment’, payload: 1 })
-
Reducer:根据 Action 返回新 State 的纯函数
-
流程:
-
工具链:
-
Redux Toolkit(RTK):官方推荐工具集,简化配置,内置 Immer(支持可变式修改)和 Thunk(异步处理)
-
react-redux:连接 Redux 与 React 组件的中间件
-
基本用法:
// 1. 定义
Reducerconst initialState = { count: 0 };
function counterReducer(state = initialState, action) {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };
default: return state;
}
}
// 2. 创建
Storeconst store = createStore(counterReducer);
// 3. 订阅状态变化
store.subscribe(() => console.log(store.getState()));
// 4. 派发
Actionstore.dispatch({ type: 'increment' });
路由管理(React Router)
-
作用:实现单页应用(SPA)的路由跳转
-
核心概念:
-
声明式导航:通过组件配置路由
- 编程式导航:通过useNavigate钩子函数跳转
- 示例(嵌套路由):
import { Routes, Route, Link } from 'react-router-dom';
function App() {
return (
<div>
<nav>
<Link to="/">首页</Link>
<Link to="/about">关于</Link>
</nav>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />}>
<Route path="detail" element={<AboutDetail />} /> {/* 嵌套路由 */}
</Route>
</Routes>
</div>
);
}
TypeScript 拓展(React + TS)
-
作用:为 React 组件添加类型定义,提升代码健壮性
-
示例:
// 组件类型定义
interface ButtonProps { text: string; onClick: () => void;}
function Button({ text, onClick }: ButtonProps) {
return <button onClick={onClick}>{text}</button>;}
// useState类型推断
const [count, setCount] = useState<number>(0); // 显式指定类型
工程化与优化
1. 性能优化
- useMemo/useCallback:缓存计算结果或函数引用,避免组件不必要的重新渲染
// useMemo:缓存计算值
const expensiveValue = useMemo(() => computeExpensiveValue(), [deps]);
// useCallback:缓存函数引用
const handleClick = useCallback(() => { ... }, [deps]);
-
虚拟 DOM diff:React 自动对比虚拟 DOM,仅更新变化的部分
-
路由懒加载:拆分代码,按需加载组件
2. 状态管理方案对比
方案 | 适用场景 | 特点 |
useState | 组件内简单状态 | 轻量,组件级作用域 |
useContext | 跨层级通信 | 避免 Props 多层传递,但性能较低 |
Redux | 复杂应用全局状态 | 集中管理,适合大型项目 |
Zustand | 轻量级全局状态 | 简单灵活,基于 Hook |
常用代码片段
- 受控表单:
const [inputValue, setInputValue] = useState('');<input value={inputValue} onChange={(e) => setInputValue(e.target.value)} />
- 获取 DOM 引用(useRef):
const inputRef = useRef<HTMLInputElement>(null);<input ref={inputRef} />useEffect(() => { inputRef.current?.focus(); // 组件挂载时聚焦输入框}, []);
- 自定义 Hook(数据请求):
function useFetch(url) { const [data, setData] = useState(null); useEffect(() => { fetch(url).then(res => res.json()).then(setData); }, [url]); return data;}// 使用const channels = useFetch('http://api.channels');