为什么推荐使用ref而不是reactive
- 局限性问题: reactive本身存在一些局限性,可能会在开发过程中引发一些问题。这需要额外的注意力和处理,否则可能对开发造成麻烦。
- 数据类型限制: reactive声明的数据类型仅限于对象,而ref则更加灵活,可以容纳任何数据类型。这使得ref更适合一般的响应式状态的声明。
- 官方推荐: 官方文档强烈建议使用ref()作为声明响应式状态的首选。这是因为ref更简单、更直观,同时避免了reactive可能引发的一些问题。
使用方法上的对比
reactive的局限性
1. 只能声明引用数据类型(对象),ref()
可以声明任意类型
let obj = reactive({
name: '小明',
age: 18
})
// 对象
const state = ref({})
// 数组
const state2 = ref([])
2. reactive
使用不当会失去响应
- 赋值给
reactive
一个整个对象或reactive
对象
let state = reactive({ count: 0 })
// 这个赋值将导致 state 失去响应
state = { count: 1 }
// 并不会触发修改 DOM ,说明失去响应了
state = reactive({ count: 11 });
解决方法
- 不要直接整个对象替换,一个个属性赋值
- 使用
Object.assign
- 使用
ref
定义对象 - 使用数组的
push
方法
let state = reactive({ count: 0 })
// state = { count: 1 } ×
state.count = 1
state = Object.assign(state, { count: 1 })
let state = ref({ count: 0 })
state.value = { count: 1 }
reactive
对象解构会失去响应,ref定义对象解构也会失去响应式
let state = reactive({ count: 0 })
// 普通解构,count 和 state.count 失去了响应性连接
let { count } = state
count++ // state.count 值依旧是 0
解决方案:
- 使用
toRefs
解构,解构后的属性是ref
的响应式变量 - ref定义对象解构也需要toRefs
const state = reactive({ count: 0 })
// 使用 toRefs 解构,后的属性为 ref 的响应式变量
let { count } = toRefs(state)
count.value++ // state.count 值改变为 1
- 将
reactive
对象的属性赋值给变量(断开连接/深拷贝) ,对该变量的赋值不会影响原来对象的属性值。
let state = reactive({ count: 0 })
// 赋值给 n,n 和 state.count 不再共享响应性连接
let n = state.count
// 不影响原始的 state
n++
console.log(state.count) // 0