一、用reactive()声明响应式状态
-
我们可以使用 reactive() 函数创建一个响应式对象或数组:
-
响应式对象其实是 JavaScript Proxy,其行为表现与一般对象相似。不同之处在于 Vue 能够跟踪对响应式对象属性的访问与更改操作。
-
要在组件模板中使用响应式状态,需要在 setup() 函数中定义并返回。
-
自然,我们也可以在同一个作用域下定义一个更新响应式状态的函数,并作为一个方法与状态一起暴露出去:
-
暴露的方法通常会被用作事件监听器:
二、reactive() 的局限性
-
仅对对象类型有效(对象、数组和 Map、Set 这样的集合类型),而对 string、number 和 boolean 这样的 原始类型 无效。
-
因为 Vue 的响应式系统是通过属性访问进行追踪的,因此我们必须始终保持对该响应式对象的相同引用。这意味着我们不可以随意地“替换”一个响应式对象,因为这将导致对初始引用的响应性连接丢失:
- 同时这也意味着当我们将响应式对象的属性赋值或解构至本地变量时,或是将该属性传入一个函数时,我们会失去响应性:
三、用 ref() 定义响应式变量
- reactive() 的种种限制归根结底是因为 JavaScript 没有可以作用于所有值类型的 “引用” 机制。
- 为此,Vue 提供了一个 ref() 方法来允许我们创建可以使用任何值类型的响应式 ref:
- ref() 将传入参数的值包装为一个带 .value 属性的 ref 对象:
- 和响应式对象的属性类似,ref 的 .value 属性也是响应式的。
- 同时,当值为对象类型时,会用 reactive() 自动转换它的 .value。
- 一个包含对象类型值的 ref 可以响应式地替换整个对象:
- ref 被传递给函数或是从一般对象上被解构时,不会丢失响应性:
- 简言之,ref() 让我们能创造一种对任意值的 “引用”,并能够在不丢失响应性的前提下传递这些引用。
1、ref 在模板中的解包
- 当 ref 在模板中作为顶层属性被访问时,它们会被自动“解包”,所以不需要使用 .value。
请注意
,仅当 ref 是模板渲染上下文的顶层属性时才适用自动“解包”。 例如, foo 是顶层属性,但 object.foo 不是。
2、ref 在响应式对象中的解包
-
当一个 ref 被嵌套在一个响应式对象中,作为属性被访问或更改时,它会自动解包,因此会表现得和一般的属性一样:
-
如果将一个新的 ref 赋值给一个关联了已有 ref 的属性,那么它会替换掉旧的 ref:
3、响应性语法糖 (实验性)
- 相对于普通的 JavaScript 变量,我们不得不用相对繁琐的 .value 来获取 ref 的值。
- 这是一个受限于 JavaScript 语言限制的缺点。
- 然而,通过编译时转换,我们可以让编译器帮我们省去使用 .value 的麻烦。
请注意它仍处于实验性阶段,在最终提案落地前仍可能发生改动。
四、<script setup>
- 在 setup() 函数中手动暴露大量的状态和方法非常繁琐。
- 幸运的是,我们可以通过使用构建工具来简化该操作。
- 当使用单文件组件(SFC)时,我们可以使用
<script setup>
来大幅度地简化代码。
<script setup>
中的顶层的导入和变量声明可在同一组件的模板中直接使用。- 你可以理解为模板中的表达式和
<script setup>
中的代码处在同一个作用域中。