《React 101》预备知识
- 文章發表於
在真正进入 React 之前,我们不妨先理解一些基本概念,无论是学习还是开发 React 都会看到这些概念的影子
HTML 结构
React 是一个用于构建用户界面的 JavaScript 库,而用户界面(网页)背后的基础就是 HTML 和树状数据结构(Tree),以下面的示例来说:
<ul><li>Apple</li><li>Banana</li><li>Peach</li></ul>
ul
是 li
的父级元素(parents),反之,对 ul
来说 li
就是子元素,而这种有父子关系的节点就是树状数据结构,我们可以对它进行任何操作,比如遍历或增删改查(CRUD)。
ul/ | \/ | \li li li(Apple)(Banana)(Peach)
DOM
开发者(我们)使用 HTML 来构建网页。当浏览器读取 HTML 代码时,会在计算机内存中为每一个 HTML 元素创建对应的对象,并将这些元素组织成树状结构:包含根节点、父节点、子节点、孙节点等,以此类推形成层次关系。这个由对象组成的树状结构就是 DOM(Document Object Model),浏览器会基于此模型进行后续的渲染处理。
同时,DOM 是可以被操作的,当浏览器完成渲染时,我们仍然可以修改 DOM 树的内容。当我们改变 DOM 时,浏览器会重新渲染(re-render),并更新用户所看到的画面。而这都是基于浏览器提供的一系列 API,比如 appendChild
、removeChild
等等。
这也说明了,如果要构建动态的网页,主要是通过操作 DOM,这就带来了一个新的议题:当网页越来越复杂时,这些操作如果没有有效优化,可能会带来一些性能上的麻烦,毕竟操作 DOM 是有成本的,浏览器必须更新 DOM 并且重新绘制(repaint),同时开发者也必须找出更有效的方法来管理这些代码。
声明式与命令式编程
声明式与命令式是两种不同的编程风格,命令式(Imperative)需要描述程序应该如何完成某件事。而声明式(Declarative)则是告诉程序你想要完成什么。
举例来说,当你想去某个地方时,命令式就像是给司机详细路线指引:「直走 500 米,在 7-11 右转,过两个红绿灯后左转...」,而声明式就像使用 Google 地图,你只需要输入目的地,系统会自动规划最佳路线。
但声明式编程本质上是建立在命令式编程之上的一层抽象,这并不代表在底层没有命令式代码。其实每一个声明式系统底下都一定有命令式代码在执行那些明确的指令。
举例来说,map
这个函数底层还是用 for 循环去实现,只是它提供一层抽象,让我们开发者在使用 map
时不需要关心循环的细节、索引管理、或是数组边界检查等问题,而能专注于「对每个元素要做什么转换」。
Array.prototype.myMap = function(callback, thisArg) {const result = [];for (let i = 0; i < this.length; i++) {if (i in this) {result[i] = callback.call(thisArg, this[i], i, this);}}return result;};// [1, 2, 3, 4, 5].myMap(x => x * 2) // [2, 4, 6, 8, 10];
同样地,当我们在 React 中写 JSX 时,底层还是会转换成一连串的 _jsx
(更早以前是 createElement)调用和 DOM 操作指令,而 React 就是帮我们处理底层命令式代码的工具,让我们更容易去打造我们的网页。