reactive | ref |
---|---|
❌ 只支持对象和数组(引用数据类型) | ✅ 支持基本数据类型 + 引用数据类型 |
✅ 在 <script> 和 <template> 中无差别使用 | ❌ 在 <script> 和 <template> 使用方式不同(在 <script> 中要使用 .value) |
❌ 重新分配一个新对象会丢失响应性 | ✅ 重新分配一个新对象不会失去响应 |
能直接访问属性 | 需要使用 .value 访问属性 |
❌ 将对象传入函数时,失去响应 | ✅ 传入函数时,不会失去响应 |
❌ 解构时会丢失响应性,需使用 toRefs | ❌ 解构对象时会丢失响应性,需使用 toRefs |
reactive 用于将对象转换为响应式数据,可以直接访问和修改属性,适用于复杂的嵌套对象和数组。
let obj = reactive({ name: '小明', age: 18 })ref 既能声明基本数据类型,也能声明对象和数组
// 对象 const state = ref({}) // 数组 const state2 = ref([])使用 ref,你可以灵活地声明基本数据类型、对象或数组,而不受像 reactive 那样只能处理引用数据类型的限制。这为开发提供了更大的灵活性,尤其是在处理不同类型的数据时。
let state = reactive({ count: 0 }) // 这个赋值将导致 state 失去响应 state = { count: 1 }赋值一个 reactive 对象
<template> {{ state }} </template> <script setup> const state = reactive({ count: 0 }) // 在 nextTick 异步方法中修改 state 的值 nextTick(() => { // 并不会触发修改 DOM ,说明失去响应了 state = reactive({ count: 11 }); }); </script>在 nextTick 中给 state 赋值一个 reactive 的响应式对象,但是 DOM 并没有更新。
let state = reactive({ count: 0 }) // state = { count: 1 } state.count = 12).使用 Object.assign
let state = reactive({ count: 0 }) // state = { count: 1 },state 不会失去响应 state = Object.assign(state, { count: 1 })3).使用 ref 定义对象
let state = ref({ count: 0 }) state.value = { count: 1 }2. 将 reactive 对象的属性赋值给变量(断开连接/深拷贝)
let state = reactive({ count: 0 }) // 赋值给 n,n 和 state.count 不再共享响应性连接 let n = state.count // 不影响原始的 state n++ console.log(state.count) // 0解决方案:
避免将 reactive 对象的属性赋值给变量。
let state = reactive({ count: 0 }) // 普通解构,count 和 state.count 失去了响应性连接 let { count } = state count++ // state.count 值依旧是 0解决方案:
const state = reactive({ count: 0 }) // 使用 toRefs 解构,后的属性为 ref 的响应式变量 let { count } = toRefs(state) count.value++ // state.count 值改变为 1二.建议:ref 一把梭
<template> {{ state.a }} {{ state.b }} {{ state.c }} </template> <script> let state = reactive({ a: 1, b: 2, c: 3 }) onMounted(() => { // 通过 AJAX 请求获取的数据,回显到 reactive,如果处理不好将导致变量失去响应 // 回显失败,给响应式数据赋值一个普通对象 state = { a: 11, b: 22, c: 333 } // 回显成功,一个个属性赋值 state.a = 11 state.b = 22 state.c = 33 }) </script>上面这个例子如果是使用 ref 进行声明,直接赋值即可,不需要将属性拆分一个个赋值。
<template> {{ state.a }} {{ state.b }} {{ state.c }} </template> <script> let state = ref({ a: 1, b: 2, c: 3 }) onMounted(() => { // 回显成功 state.value = { a: 11, b: 22, c: 333 } }) </script>给响应式对象的字面量赋一整个普通对象或 reactive 对象将导致 reactive 声明的响应式数据失去响应。