Vue3 01.响应式
ref
在组合式API中,推荐使用ref()函数来声明响应式状态:
import { ref } from 'vue' |
ref
函数中接收的参数为需要包装为响应式对象的数据,函数会将数据包装在value
属性中返回对应的响应式对象。修改该属性,将会触发页面更新。
const increment = () => count.value++ |
在template
中使用ref响应式对象并不需要使用value
属性,模板会自动进行解包。
<template> |
深层响应性
ref
可以持有任何类型的值,包括深层嵌套的对象、数组或者Map之类的。ref
会使它的值具有深层响应性,所以在修改内部数据时,这个变化仍旧能被检测到:
<script setup> |
使用shallowRef
函数可以放弃深层响应性,这种情况下对于浅层ref
,只有.value
的变动响应会被捕获。
reactive
与将数据包装在内部响应式对象的ref
不同,reactive
将会使对象本身具有响应性。
<script setup> |
reactive
创建的响应式对象不需要使用.value
属性来访问,而是直接访问本身属性即可。与ref
一样的是reactive
也会深层转换对象为响应式对象,所以对应的也有shallowReactive
函数来放弃深层响应性。
reactive
的局限性
- 有限的值类型,只能用于对象类型的数据,不能持有
string
,number
或者boolean
之类的基本类型数据。 - 不能替换整个对象,Vue的响应式是通过属性访问实现的,所以必须始终保持对响应式对象的同一引用,一旦修改整个对象,那么引用就断开,页面就不会更新了。
let state = reactive({count: 0}) |
- 对解构操作不友好,当对响应式对象进行解构时,解构后属性已经丢失了响应性连接:
const state = reactive({count: 0}) |
由于这些限制,建议使用
ref
作为声明响应式的主要API
模板中的解包注意事项
在模板渲染上下文中,只有顶级的ref
属性才会被解包。
//count和object是顶级ref属性,object.id不是 |
渲染的结果将会是[object object]1
,因为在计算表达式时object.id
没有被解包,仍然是一个ref
对象。
DOM更新时机
当修改了响应式状态,DOM会被自动更新。DOM的更新是异步的,Vue会在”next tick”更新周期中缓冲所有状态的修改,来确保不管进行了多少次状态修改,每个组件只会被更新一次。
要等待DOM更新完再执行额外的代码,可以使用nextTick()
全局API:
import { nextTick } from 'vue' |