Skip to content

引言

前文没有提到响应系统,响应系统也是 Vue.js 的重要组成部分,所以我们会花费大量篇幅介绍。在本章中,我们首先讨论什么是响应式数据和副作用函数, 然后尝试实现一个相对完善的响应系统。在这个过程中,我们会遇到各种各样的问题,例如如何避免无限递归?为什么需要嵌套的副作用函数? 两个副作用函数之间会产生哪些影响?以及其他很多需要考虑的细节。接着,我们会详细讨论与响应式数据相关的内容。 我们知道 Vue.js 3 采用Proxy 实现响应式数据,这涉及语言规范层面的知识。这部分内容包括如何根据语言规范实现对数据对象的代理, 以及其中的一些重要细节。接下来,我们就从认识响应式数据和副作用函数开始,一步一步地了解响应系统的设计与实现。

副作用函数指的是会产生副作用的函数,如下面的代码所示:

js
function effect() {
  document.body.innerText = 'hello vue3'
}

当 effect 函数执行时,它会设置 body 的文本内容,但除了 effect 函数之外的任何函数都可以读取或设置 body 的文本内容。 也就是说,effect 函数的执行会直接或间接影响其他函数的执行,这时我们说 effect 函数产生了副作用。副作用很容易产生, 例如一个函数修改了全局变量,这其实也是一个副作用,如下面的代码所示:

js
// 全局变量
let val = 1

function effect() {
  val = 2 // 修改全局变量,产生副作用
}

理解了什么是副作用函数,再来说说什么是响应式数据。假设在一个副作用函数中读取了某个对象的属性:

js
const obj = { text: 'hello world' }
function effect() {
  // effect 函数的执行会读取 obj.text
  document.body.innerText = obj.text
}

如上面的代码所示,副作用函数 effect 会设置 body 元素的 innerText 属性,其值为 obj.text, 当 obj.text 的值发生变化时,我们希望副作用函数effect 会重新执行:

js
// 修改 obj.text 的值,同时希望副作用函数会重新执行
obj.text = 'hello vue3'

这句代码修改了字段 obj.text 的值,我们希望当值变化后,副作用函数自动重新执行,如果能实现这个目标,那么对象 obj 就是响应式数据。 但很明显,以上面的代码来看,我们还做不到这一点,因为 obj 是一个普通对象,当我们修改它的值时,除了值本身发生变化之外,不会有任何其他反应。 下一节中我们会讨论如何让数据变成响应式数据。

如有转载或CV请标注本站原文地址