ref()
创建响应式数据:
ref() 可以用来创建任何类型的响应式数据,不仅限于基本类型,还可以是对象、数组、Map等复杂数据结构。
####需要直接访问值:
返回的 ref 对象只有一个指向其内部值的属性 .value,通过它来读取或修改实际的值。
const name = ref('Alice’)
console.log(name.value) // Alice
注意:name变量不具有响应式,name.value才具有响应式。
模板自动解包:
在template中使用 ref 时,我们不需要附加 .value。当在template中使用时,ref 会自动解包。
<template>
<div>{{ count }}</div>
</template>
<script setup>
import { ref } from 'vue'
const count = ref(0)
console.log(count.value) // 0
</script>
深度响应式:
ref()将使其值具有深度响应式,即使改变嵌套对象或数组时,变化也会被检测到。
import { ref } from 'vue'
const obj = ref({
nested: { count: 0 },
arr: ['foo', 'bar']
})
function mutateDeeply() {
// 以下都会按照期望工作
obj.value.nested.count++
obj.value.arr.push('baz')
}
reactive()
创建响应式对象:
reactive() :接收一个普通对象作为参数,返回对象的响应式代理。
const state = reactive({ count: 0, name: 'Alice' })
state 对象及其所有嵌套的属性,(如 state.count 和 state.name)都具有响应式。
不能用于原始类型:
它只能用于对象类型 (对象、数组和如 Map、Set 这样的集合类型)。它不能持有如 string、number 或 boolean 这样的原始类型。
深度响应式:
reactive() 不仅使顶层对象本身响应式,还会递归地将对象内部的属性(无论多么深层次)以及数组的元素转变为响应式。
不能替换整个对象:
由于 Vue 的响应式跟踪是通过属性访问实现的,因此我们必须始终保持对响应式对象的相同引用。
let state = reactive({name: 'Alice' })
// 上面的 ({ count: 0 }) 引用将不再被追踪
// (响应性连接已丢失!)
state = reactive({ count: 1 })
不能替换整个对象,可以使用 Object.assing() 合并对象。
import { ref, reactive } from 'vue'
const user = reactive({ name: 'Alice' })
Object.assign(user, { name: 'Tony', age: 18 })
console.log(user.name, user.age) // Tony 18
解构赋值丢失响应式:
当我们将响应式对象的原始类型属性解构为本地变量时,或者将该属性传递给函数时,我们将丢失响应性连接:
const state = reactive({ count: 0 })
// 当解构时,count 已经与 state.count 断开连接
let { count } = state
// 不会影响原始的 state
count++
// 该函数接收到的是一个普通的数字
// 并且无法追踪 state.count 的变化
应用场景:
比如表单对象、状态对象。
toRefs()
属性转换:
将一个响应式对象转换为一个普通对象,这个普通对象的每个属性都是指向源对象相应属性的 ref。虽然 toRefs() 返回的对象是普通对象,但它内部的属性实际上是 ref。因此,在访问或修改属性值时,需要使用 .value。
方便解构赋值:
由于返回对象的属性已经是 ref,可以直接进行解构赋值,且在解构后仍能保持响应性。这解决了响应式丢失问题。
示例代码:
import { reactive, toRefs } from 'vue';
// 创建一个响应式对象
const state = reactive({
name: 'Alice',
age: 25,
address: {
city: '北京'
}
});
// 使用 toRefs 转换为独立的 ref
const stateAsRefs = toRefs(state);
// 现在可以解构赋值并保持响应性
const { name, age, address } = stateAsRefs;
// 改变 ref 值会触发视图更新
name.value = 'Bob';
address.value.city = '广州';