Skip to content
This page has been auto-translated and may contain errors.View in English

React 是什么?

一个有按钮的页面需要在每次点击时保持计数器与按钮同步。用原生 JavaScript 写,你得抓住按钮的文本节点,添加点击监听器,每次有人点击时手动更新数字。再加个搜索过滤、购物车总数和一个会打开关闭的弹窗,代码里就散落一堆手动更新的逻辑了,每一处都可能在页面其他地方数据改变时埋下 bug。

React 是一个用组件构建用户界面的 JavaScript 库,它把这种繁琐的手工记账工作从你身上拿走了。这章我们来看看这在实际中意味着什么:React 背后的核心理念、它在哪儿运行,以及它怎样回答初学者常问的"库还是框架"这个问题。

组件和核心理念

这是用 React 组件写的同一个点击计数器:

jsx
import { useState } from 'react'

function Counter() {
  const [count, setCount] = useState(0)

  return (
    <button onClick={() => setCount(count + 1)}>
      Clicked {count} times
    </button>
  )
}

这个例子用了一些你还没见过的东西:return 里面的标记是 JSX,useState 是一个 hook,onClick 是事件处理器。组件JSX 这两章会讲那个标记,State 会完整讲解 useStateEvents 会讲 onClick,所以现在你先信任这个语法,跟着理念的脉络走就行。

count 是状态。Counter 返回的 JSX 描述的是这个按钮对应这个状态应该显示什么样子。点击按钮会调用 setCount,更新 count,然后 React 重新渲染按钮来匹配新状态。你永远不用直接碰按钮的文本。你为新值重新描述它一遍,React 会算出页面上什么变了。

这就是藏在每个 React 组件下面的核心理念:你把 UI 描述成数据(通常叫状态)的函数,React 负责更新 DOM 来匹配。一个**组件**是一个返回 UI 片段的函数,一个应用就是一棵组件树,所有组件都以上面计数器的方式工作。

这里值得精确对比的是声明式和命令式。命令式代码,也就是直接 DOM 操作,把步骤拼出来:找到这个元素,改它的文本,加这个 class。声明式代码,也就是组件返回的东西,拼出来的是最终状态:给定这个数据,按钮应该显示成这样。React 负责中间的那些步骤。

这些步骤通过一个虚拟 DOM 来跑:一个轻量级的内存里 UI 表示,React 从你组件返回的东西构建它,和前一个版本比对,然后算出最少需要改哪些真实 DOM。这东西存在,现在先不用管它也没事。你不创建它、不读它、不直接管理它;这是 React 内部的机制,用来实现模型中"让 DOM 匹配"那一半的。

剩下一个值得记住的心智模型,贯穿这整个手册:UI = f(state)。组件是它数据的函数,hook、重新渲染、副作用全都建立在这一个理念上面。后面你看到的大多数看起来像是独立的 React 概念,其实都是这一个理念的后果。

React 在哪儿运行

React 主要在浏览器里运行,把组件渲染到 DOM。这也是这份手册始终待在的环境。

但 React 的组件模型并不是绑死在 DOM 上的。其他渲染器可以把同一个模型接到不同的地方。最有名的例子是 React Native,它用 React 的组件和状态模型来驱动原生移动界面而不是网页。这里提一下是因为不想你后面看到这个名字时被吓一跳。教它超出了这份手册的范围。

库还是框架?

React 负责渲染 UI。它不附带路由,不决定你怎样加载数据,也不处理服务端渲染。这些都是你自己的选择,通常要配合别的工具来做。这就是 React 算作库而不是完整框架的实际原因:它把一件事做好,剩下的留给你,而不是像框架那样拥有整个应用。

各种框架的类型完整讲了这个区别,包括 React 跟 Next.js 这样东西怎样放在一起,Next.js 会补上那些缺失的部分。

JunoUI 作为状态的函数 React 的全部核心就是一个习惯:描述屏幕对你现有数据应该长什么样,让 React 负责改变它。你不用伸手进页面手动编辑,你说它应该显示什么,React 就跟着做。

它在哪儿运行,浏览器里还是 React Native 这样的地方,这是后来的细节。现在关键是这个习惯。

JunoUI 作为状态的函数 养成把组件写成状态函数的习惯:给定这个数据,渲染这样。你每次写的时候都在做这件事,不管是按钮上的点击计数还是整个页面。

React 负责处理 DOM 更新,这样你就不用手动写了。它算作库而不是框架,这是准确的:它负责渲染 UI,路由、数据加载和渲染策略都留给你自己。

JunoUI 作为状态的函数 把 UI = f(state) 作为后面一切的框架来记住。组件是数据的函数,虚拟 DOM 是 React 自己的记账方式,用来把一次渲染变成下一组 DOM 改动,而声明式在这里赢过命令式,因为你不用自己追踪更新步骤。

这就是为什么它算作库而不是框架:它到渲染为止,路由、数据获取和服务端渲染都留给你配合的工具。

接下来:历史和版本,讲的是 React 怎样发展到今天的,还有各个版本都改了什么。