当前位置:嗨网首页>书籍在线阅读

03-什么是状态

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

3.1.1 什么是状态

让我们简单地看看状态,以便当我们查看React中的状态时可以更好地理解它。即使之前从未明确地思考过或听说过程序中的“状态”,但至少可能见过它。大部分程序都可能有一些与它们对应的状态。如果你之前用过诸如Vue、Angular和Ember这样的前端框架,那么几乎可以肯定你一定编写过拥有某种状态的UI。React组件也有状态。那么当谈及“状态”时,我们究竟讨论的是什么?试试下面这个定义。

状态  程序在特定瞬间可访问的所有信息。

这是一个简化的定义,这个定义可能忽略了一些学术上的细微差别,但就我们的目的而言已经足够了。许多学者编写了大量论文致力于精确定义计算机系统中的状态,但对我们而言,状态是程序在一瞬间可访问的信息。这包括,在某个特定时刻无须任何额外的赋值或计算就能够引用的所有值,换句话说,它是瞬间对某个程序的了解的快照。

例如,这可能包括先前创建的任何变量或其他可用的值。当改变一个变量(而不是用它获取值时),程序的状态就会被改变,它与之前不一样了。仅通过读取你就可以检索给定时刻的状态,但当你随着时间的推移而进行了某些修改,程序的状态就会变化。从技术上讲,机器的底层状态在使用时每时每刻都在变化,但我们只关心程序的状态。

让我们看一些代码并逐句检查代码清单3-1中的简单的程序状态。我们不会深入那些发生在幕后的所有底层分配或过程,我们只是尝试更清晰地认识程序中的数据,以便更容易思考React组件。

代码清单3-1 简单的程序状态

const letters = 'Letters';  ⇽--- 在名为letters的变量中保存一个字符串
const splitLetters = letters.split('');  ⇽--- 将letters切分为一个字符串数组
console.log("Let's spell a word!");  ⇽--- 打印出一条消息
splitLetters.forEach(letter => console.log(letter));  ⇽--- 打印出每个字母

代码清单3-1展示了一个简单的脚本,它进行了一些基本赋值和数据操作并将其输出到控制台。这虽然很乏味,但我们可以用它来更多地了解状态。Javascript采用所谓的“运行至完成”(run to completion)语义,这意味着程序将按照通常被认为的顺序从上到下执行。JavaScript引擎常常会以意想不到的方式优化代码,但它仍然以与原始代码一致的方式运行。

尝试从上到下逐行阅读代码清单3-1中的代码。如果想用浏览器的调试器执行它,转至https://codesandbox.io/s/n9mvol5x9p。打开浏览器的开发者工具,逐步执行每行代码并查看所有的变量赋值和其他东西。

考虑到我们的目的,让我们将每行代码当作某个时间点。就状态的简单定义“程序在特定瞬间可访问的所有信息”,如何描述应用在某个时刻的状态?注意,我们让事情简单化了并忽略了闭包、垃圾收集等。

(1) letters 是一个变量,将字符串“Letters”赋值给它。

(2)通过从 letters 拆分出每个字符创建了 splitLettersletters 仍旧可用。

(3)来自步骤1和步骤2的所有信息都可用,一个消息被发送到控制台。

(4)程序遍历数组中的每一项并打印输出一个字符。这一过程可能瞬间发生几次,因此对 Array.forEach 可用的信息对程序也可用。

随着程序向前执行,状态随时间发生变化,更多的信息变得可用,因为任何信息都没有被删除而且引用也没有被改变。表3-1展示了可用信息是如何随着程序向前执行而增加的。

表3-1 每一步的状态

| 步骤 | 程序可用的状态 | | :----- | :----- | :----- | :----- | | 1 | letters = "Letters" | | 2 | letters = "Letters" | splitLetters = ["L", "e", "t", "t", "e", "r", "s"] | | 3 | letters = "Letters" | splitLetters = ["L", "e", "t", "t", "e", "r", "s"] | | 4 | letters = "Letters" | splitLetters = ["L", "e", "t", "t", "e", "r", "s"] | 对于从0到 splitLetters 长度的各子步骤: | letter = "L" (接着是 "e""t" 等) |

试着走查自己的代码并思考程序的每一行可以用什么信息。我们倾向于简化代码——这里正是这样做的,因为我们不必一次性考虑每个可能的维度——但即便是对于简单的程序也有大量的信息可用。

我们可以认真考虑的一个因素是,当运行的程序变得相当复杂时(就像最简单的UI也倾向于变得复杂),对其的推理认知会变得很困难。我的意思是,系统的复杂性可能很难一下子都记住,而且系统中的逻辑很难让人彻底想清楚。大多数程序就是如此,但涉及UI构建时则尤为困难。

现代浏览器应用的UI常常代表了多种技术的交集,包括服务器提供数据、样式和布局API、JavaScript框架、浏览器API等。UI框架上的进展旨在简化这个问题,但它仍是一个挑战。随着Web应用越来越普及并融入社会和日常生活中,这个挑战往往会随着人们对这些应用的期望变大而增加。如果React是有用的,它需要帮助我们减少或屏蔽一些现代UI的极度复杂的状态。希望诸位会认识到React确实能做到这一点。但如何做到的呢?一种方法是提供两个处理数据的特定API:属性(props)和状态(state)。