组件化是现代前端开发的核心理念。React 将用户界面抽象为一个个独立的组件,每个组件负责一块独立的 UI 功能。
什么是组件:
组件是 UI 的独立、可复用的代码片段。从概念上看,组件就像 JavaScript 函数,接收任意的输入(称为 props),返回描述页面应该显示什么的 React 元素。
组件化的好处:
组件的层次结构:
React 应用本质上是一棵组件树。顶层是根组件(通常是 App),下面是各种子组件。这种树状结构让数据流动清晰可控。
DOM 操作的问题:
浏览器中的 DOM 操作是昂贵的。每次修改 DOM,浏览器都需要重新计算布局、重绘页面。频繁的 DOM 操作会导致页面卡顿。
虚拟 DOM 的解决方案:
React 引入了虚拟 DOM(Virtual DOM)的概念。虚拟 DOM 是真实 DOM 的轻量级 JavaScript 对象表示。
工作流程:
1. 当状态变化时,React 首先更新虚拟 DOM 2. React 比较新旧虚拟 DOM(Diff 算法) 3. 计算出最小的 DOM 变更集合 4. 批量执行实际的 DOM 更新
Diff 算法:
React 的 Diff 算法基于以下假设:
1. 不同类型的元素会产生不同的树 2. 开发者可以通过 key 属性提示哪些子元素是稳定的
这使得 Diff 算法的时间复杂度从 O(n³) 降低到 O(n)。
Reconciliation(协调):
协调是 React 更新 DOM 的过程。当组件的 props 或 state 变化时,React 会重新渲染组件,生成新的虚拟 DOM 树,然后与旧的虚拟 DOM 树进行比较,最后更新真实 DOM。
什么是 JSX:
JSX 是一种 JavaScript 语法扩展,它让你在 JavaScript 中编写类似 HTML 的代码。
const element = <h1>Hello, world!</h1>;
这段代码看起来像 HTML,但实际上是 JavaScript。Babel 等工具会将 JSX 转换为 React.createElement() 调用。
JSX 的优点:
JSX 的规则:
数据流动的方向:
React 采用单向数据流(Unidirectional Data Flow):
为什么要单向数据流:
状态提升示例:
当多个组件需要共享状态时,将状态提升到它们的共同父组件中。父组件通过 props 将状态传递给子组件,子组件通过回调函数通知父组件更新状态。
声明式 vs 命令式:
命令式编程关注“怎么做”:
// 命令式:一步一步告诉计算机怎么做 const list = document.getElementById('list'); list.innerHTML = ''; for (let i = 0; i < items.length; i++) { const li = document.createElement('li'); li.textContent = items[i]; list.appendChild(li); }
声明式编程关注“做什么”:
// 声明式:描述界面应该是什么样子 function TodoList({ items }) { return ( <ul> {items.map(item => <li key={item.id}>{item.text}</li>)} </ul> ); }
React 的声明式优势:
受控组件:
表单元素的值由 React 组件的 state 控制。用户的输入会触发 onChange 事件,更新 state,state 的变化又会重新渲染组件。
function ControlledInput() { const [value, setValue] = useState(''); return ( <input value={value} onChange={e => setValue(e.target.value)} /> ); }
非受控组件:
表单元素的值由 DOM 自身管理。通过 ref 获取 DOM 节点的值。
function UncontrolledInput() { const inputRef = useRef(null); const handleSubmit = () => { console.log(inputRef.current.value); }; return ( <> <input ref={inputRef} defaultValue="" /> <button onClick={handleSubmit}>提交</button> </> ); }
选择建议:
浏览器事件的差异:
不同浏览器的事件处理存在差异。React 通过合成事件系统(SyntheticEvent)抹平了这些差异。
合成事件的特点:
常用合成事件:
首次渲染(Mount):
1. 调用组件函数/类,生成虚拟 DOM 2. 递归渲染所有子组件 3. 将虚拟 DOM 转换为真实 DOM 4. 插入到页面中 5. 执行副作用(如 useEffect)
更新渲染(Update):
1. 状态或 props 变化,触发重新渲染 2. 生成新的虚拟 DOM 3. Diff 算法比较新旧虚拟 DOM 4. 计算最小更新集合 5. 批量更新真实 DOM
卸载(Unmount):
1. 清理副作用(如 useEffect 的返回函数) 2. 从 DOM 中移除组件 3. 释放相关资源
不必要的渲染:
组件的 state 或 props 变化时,React 会重新渲染组件及其所有子组件。这可能导致不必要的渲染。
优化策略:
本章介绍了 React 的核心概念:组件化、虚拟 DOM、JSX、单向数据流、声明式编程等。理解这些概念是掌握 React 的基础。
在下一章,我们将开始搭建 React 开发环境,编写第一个 React 应用。