目录

第二章:React 基础概念

2.1 组件化思想

组件化是现代前端开发的核心理念。React 将用户界面抽象为一个个独立的组件,每个组件负责一块独立的 UI 功能。

什么是组件

组件是 UI 的独立、可复用的代码片段。从概念上看,组件就像 JavaScript 函数,接收任意的输入(称为 props),返回描述页面应该显示什么的 React 元素。

组件化的好处

组件的层次结构

React 应用本质上是一棵组件树。顶层是根组件(通常是 App),下面是各种子组件。这种树状结构让数据流动清晰可控。

2.2 虚拟 DOM

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。

2.3 JSX

什么是 JSX

JSX 是一种 JavaScript 语法扩展,它让你在 JavaScript 中编写类似 HTML 的代码。

const element = <h1>Hello, world!</h1>;

这段代码看起来像 HTML,但实际上是 JavaScript。Babel 等工具会将 JSX 转换为 React.createElement() 调用。

JSX 的优点

JSX 的规则

2.4 单向数据流

数据流动的方向

React 采用单向数据流(Unidirectional Data Flow):

为什么要单向数据流

状态提升示例

当多个组件需要共享状态时,将状态提升到它们的共同父组件中。父组件通过 props 将状态传递给子组件,子组件通过回调函数通知父组件更新状态。

2.5 声明式编程

声明式 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 的声明式优势

2.6 受控组件与非受控组件

受控组件

表单元素的值由 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>
    </>
  );
}

选择建议

2.7 合成事件

浏览器事件的差异

不同浏览器的事件处理存在差异。React 通过合成事件系统(SyntheticEvent)抹平了这些差异。

合成事件的特点

常用合成事件

2.8 组件的渲染过程

首次渲染(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. 释放相关资源

2.9 React 的渲染优化

不必要的渲染

组件的 state 或 props 变化时,React 会重新渲染组件及其所有子组件。这可能导致不必要的渲染。

优化策略

2.10 总结

本章介绍了 React 的核心概念:组件化、虚拟 DOM、JSX、单向数据流、声明式编程等。理解这些概念是掌握 React 的基础。

在下一章,我们将开始搭建 React 开发环境,编写第一个 React 应用。