React
1. React 是什么?核心特点
React 是 Meta 开源的 JavaScript UI 库,专注于构建用户界面。核心特点:
- 声明式编程:描述 UI 状态,React 自动处理 DOM 更新。
- 组件化:UI 拆分为独立可复用的组件。
- 单向数据流:数据从父组件流向子组件,可预测、易调试。
- 虚拟 DOM + Fiber:高效更新,可中断渲染。
- JSX:JavaScript 语法扩展,允许在 JS 中写类似 HTML 的标记。
2. JSX
JSX 是 React.createElement 的语法糖。
// JSX 写法
const element = <h1 className="title">Hello React</h1>;
// 编译后
const element = React.createElement('h1', { className: 'title' }, 'Hello React');
浏览器无法识别 JSX,需要通过 Babel 编译为普通 JS 代码才能执行
3、组件间通信
| 方式 | 适用场景 | 示例 |
|---|---|---|
| Props | 父→子传递数据 | <Child message={msg} /> |
| 回调函数 | 子→父传递数据 | 父传函数给子,子调用 props.onChildData(data) |
| Context API | 跨层级组件通信(避免 props 逐层传递) | createContext + useContext |
| 状态管理库 | 大型应用全局状态 | Redux Toolkit、Zustand、Jotai |
| Refs | 直接访问 DOM 或子组件实例 | useRef + ref 属性 |
| 自定义 Hooks | 复用状态逻辑 | useAuth、useFetch 等 |
| 高阶组件(HOC) | 共享逻辑(较少使用,Hooks 更优) | 接收组件返回增强组件 |
| Event Bus(事件总线) | 任意组件通信(非 React 原生) | mitt 等第三方库 |
createContext、useContext 示例:
import { createContext, useContext, useState } from 'react';
// 1. 创建 Context 对象
const ThemeContext = createContext('light'); // 参数是默认值
// 2. Provider 组件:提供数据
function App() {
const [theme, setTheme] = useState('dark');
return (
<ThemeContext.Provider value={{ theme, setTheme }}>
<Toolbar />
</ThemeContext.Provider>
);
}
// 3. 后代组件消费数据
function Toolbar() {
return <ThemedButton />;
}
function ThemedButton() {
const { theme, setTheme } = useContext(ThemeContext); // 方式一:useContext
return (
<button onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}>
当前主题:{theme}
</button>
);
}
4、API
4.1 内置 Hooks
4.2 内置组件
这些是可以在 JSX 中使用的 React 内置组件,以 Symbol 常量形式导出。
4.3 工具类 API
4.4 通用 DOM API
| API | 说明 |
|---|---|
createPortal | 允许将子组件渲染到 DOM 树中父组件 DOM 层次之外的不同位置,常用于模态框、全局提示等。 |
flushSync | 强制 React 同步执行状态更新并立即刷新 DOM。 |
4.5 资源预加载 API
这些 API 用于预加载脚本、样式表、字体等资源,从而让应用更快。基于 React 的框架通常会自动处理资源加载。
4.6 通用 DOM API
| API | 说明 |
|---|---|
createPortal | 允许将子组件渲染到 DOM 树中父组件 DOM 层次之外的不同位置,常用于模态框、全局提示等。 |
flushSync | 强制 React 同步执行状态更新并立即刷新 DOM。 |
5、React Router(路由)
React Router v6 完全利用 Hooks 重构。
核心组件
| 组件 | 作用 |
|---|---|
BrowserRouter | history 模式路由容器 |
HashRouter | hash 模式路由容器 |
Routes / Route | 定义路由规则 |
Link / NavLink | 声明式导航 |
Outlet | 嵌套路由占位符 |
核心 Hooks
| Hook | 作用 |
|---|---|
useParams | 获取路由参数 |
useLocation | 获取当前 location 对象 |
useNavigate | 程序化导航 |
useRoutes | 配置式路由(替代 Routes + Route) |
6、React-Redux
| API | 说明 |
|---|---|
<Provider store> | 顶层组件,使 store 对下层组件可用。 |
connect(mapStateToProps, mapDispatchToProps, mergeProps, options) | 高阶组件(HOC),将 store 中的 state 和 dispatch 映射到组件的 props。 |
useSelector(selector) | Hook,从 store 中提取数据,当数据变化时强制组件重新渲染。 |
useDispatch() | Hook,返回 store 的 dispatch 函数。 |
useStore() | Hook,返回 store 实例本身(不常用)。 |
Redux 现代推荐: (Redux Toolkit + React-Redux Hooks )
必须掌握的核心 API
| API | 作用 | 一句话说明 |
|---|---|---|
configureStore | 创建 store | 像 createStore 但更智能,自动加 thunk 和 DevTools |
createSlice | 同时生成 reducer 和 action creators | 传入 name、initialState、reducers 对象,自动生成 |
createAsyncThunk | 处理异步 action | 自动生成 pending/fulfilled/rejected 三个 action,并在 extraReducers 中处理 |
// store.js
import { configureStore, createSlice, createAsyncThunk } from '@reduxjs/toolkit';
// 1. 同步 slice
const counterSlice = createSlice({
name: 'counter',
initialState: { value: 0 },
reducers: {
increment: state => { state.value += 1 }, // 直接“修改”
decrement: state => { state.value -= 1 },
incrementByAmount: (state, action) => { state.value += action.payload }
}
});
// 2. 异步 thunk
export const fetchUser = createAsyncThunk('user/fetch', async (userId) => {
const res = await fetch(`/api/user/${userId}`);
return res.json();
});
// 3. 异步 slice (处理 thunk 的三种状态)
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;
});
}
});
// 导出 action creators 和 reducer
export const { increment, decrement, incrementByAmount } = counterSlice.actions;
const store = configureStore({
reducer: {
counter: counterSlice.reducer,
user: userSlice.reducer
}
});
export default store;
React-Redux Hooks —— 在组件里用状态
两个核心 Hook
| Hook | 作用 | 类比 |
|---|---|---|
useSelector | 从 store 中读取数据 | 类似 mapStateToProps |
useDispatch | 拿到 dispatch 函数 | 类似 mapDispatchToProps |
使用步骤(配合上面的 store)
1. 顶层用 Provider 包裹
// main.jsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import { Provider } from 'react-redux';
import store from './store';
import App from './App';
ReactDOM.createRoot(document.getElementById('root')).render(
<Provider store={store}>
<App />
</Provider>
);
2. 组件内读取和派发
// Counter.jsx
import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { increment, decrement, incrementByAmount } from './store';
function Counter() {
// 读取状态
const count = useSelector(state => state.counter.value);
const dispatch = useDispatch();
return (
<div>
<span>{count}</span>
<button onClick={() => dispatch(increment())}>+1</button>
<button onClick={() => dispatch(decrement())}>-1</button>
<button onClick={() => dispatch(incrementByAmount(5))}>+5</button>
</div>
);
}
3. 异步 thunk 的派发
import { fetchUser } from './store';
function UserProfile({ userId }) {
const dispatch = useDispatch();
const { data, loading, error } = useSelector(state => state.user);
useEffect(() => {
dispatch(fetchUser(userId));
}, [userId]);
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error}</div>;
return <div>{data?.name}</div>;
}
7、React 底层原理
1. 虚拟 DOM
- 减少频繁的真实 DOM 操作
- 跨平台(React Native)
- 便于 diff 算法计算差异
2. Diff 算法
- 同层比较,不跨层级
- 类型不同 → 直接销毁重建
- 类型相同 → 对比属性
- 列表靠 key 识别节点复用,复杂度优化到 O(n)
为什么 key 不能用 index?
数组增删前置元素会导致 index 错乱,引发组件状态错位、DOM 复用错误。应使用唯一稳定的业务 id。
3. Fiber 架构(React 16+)
两个阶段:
- Render 阶段:可中断、分片、优先级调度,遍历构建 Fiber 树
- Commit 阶段:不可中断,一次性更新 DOM、布局、绘制
4. React 更新流程
触发 setState → 生成更新任务 → Fiber 调和(可中断)→ 收集 DOM 变更 → Commit 一次性渲染 → 浏览器绘制
5. 合成事件
React 自己实现了一套事件系统(事件委托到 root 节点),性能高,与原生事件混用时,原生先执行 → 合成后执行,阻止冒泡互不生效。