响应式基础
响应式基础
使用 reactive()
函数创建一个响应式对象或数组:
<script setup> import { reactive } from 'vue' const state = reactive({ count: 0 }) function increment() { state.count++ } </script> <template> <button @click="increment"> {{ state.count }} </button> </template>
DOM 更新时机
当你更改响应式状态后,DOM 会自动更新。然而,你得注意 DOM 的更新并不是同步的。相反,Vue 将缓冲它们直到更新周期的 “下个时机” 以确保无论你进行了多少次状态更改,每个组件都只更新一次。
若要等待一个状态改变后的 DOM 更新完成,你可以使用 nextTick() 这个全局 API:
import { nextTick } from 'vue' function increment() { state.count++ nextTick(() => { // 访问更新后的 DOM }) }
深层响应性
import { reactive } from 'vue' const obj = reactive({ nested: { count: 0 }, arr: ['foo', 'bar'] }) function mutateDeeply() { // 以下都会按照期望工作 obj.nested.count++ obj.arr.push('baz') }
reactive()
的局限性
reactive()
API 有两条限制:
-
仅对对象类型有效(对象、数组和
Map
、Set
这样的集合类型),而对string
、number
和boolean
这样的 原始类型 无效。 -
因为 Vue 的响应式系统是通过属性访问进行追踪的,因此我们必须始终保持对该响应式对象的相同引用。这意味着我们不可以随意地“替换”一个响应式对象,因为这将导致对初始引用的响应性连接丢失:
响应性语法糖
相对于普通的 JavaScript 变量,我们不得不用相对繁琐的 .value
来获取 ref 的值。这是一个受限于 JavaScript 语言限制的缺点。然而,通过编译时转换,我们可以让编译器帮我们省去使用 .value
的麻烦。Vue 提供了一种编译时转换,使得我们可以像这样书写之前的“计数器”示例:
<script setup> let count = $ref(0) function increment() { // 无需 .value count++ } </script> <template> <button @click="increment">{{ count }}</button> </template>