获取响应式数据
API | 传入 | 返回 | 备注 |
---|---|---|---|
reactive | plain-object | 对象代理 | 深度代理对象中的所有成员 |
readonly | plain-object or proxy | 对象代理 | 只能读取代理对象中的成员,不可修改 |
ref | any | { value: … } | 对value的访问是响应式的,如果传入的值是一个对象,则会通过reactive代理,如果已经是代理,则直接使用代理 |
computed | function | { value: … } | 读取value值时,会根据情况决定是否要运行函数 |
应用
- 如果想让一个对象变为响应式数据,使用reactive或者ref
- 如果想让一个对象只读,使用readonly
- 如果想让一个非对象数据变为响应式,使用ref
- 如果想根据一个响应式数据得到另一个响应式数据,使用computed
注意点
const state = reactive({a:1}) // 数据源,不暴露
const imState = readonly(state) // 暴露出一个不可更改的对象
const setValue = (val) => {
state.a = val // 设置
}
return {
imState,
setValue
}
- 导出一个用户不可随意更改的对象,仅能通过作者提供的方法更改
- cumputed传入的函数不会直接调用,当用到函数内部的响应式数据时,会在使用这个响应式数据之前调用,且具有缓存,当数据不变时函数不会重复执行
- 使用…解构reactive或者readonly,或者使用 { a } = state这种格式得到的数据不具有响应式 解决办法:使用toRefs
监听数据变化
watchEffect
const watch = watchEffect(()=> {
// 该函数会立即执行,记录响应式数据,当其变化时,会放入微队列执行
})
// 返回一个函数,调用这个函数会停止监听
watch(); // 停止监听
watch
// 监听单个数据的变化
const state = reactive({a: 1})
watch(
()=> state.a,
(newValue, oldValue)=> {
// ... 微队列调用
},
options // 配置参数对象 如immediate
)
const count = ref(0)
watch(
count,
(newValue, oldValue)=> {
// ...
},
options // 配置参数对象 如immediate
)
// 监听多个数据的变化
watch(
[()=> state.a, count],
([newValue1, newValue2], [oldValue1, oldValue2])=> {
// ...
},
options
)
应用
除了以下场景,其余都建议使用watchEffect
- 不希望回调函数一开始就执行
- 数据改变时,需要参考旧值
- 需要监控一些回调函数中不会用到的数据
判断
- isProxy 是否由reactive或者readonly创建
- isReactive 是否由reactive创建
- isReadonly 是否是有readonly创建
- isRef 是否是一个ref对象
转换
unref
等同于 isRef(val) ? val.value : val
使用: const a = unref(b)
toRef
得到一个响应式对象某个属性的ref格式
const state = reactive({a: 1})
const aRef = toRef(state, 'a')
aRef.value++
console.log(state.a) // 2
state.a++
console.log(aRef.value) // 3
toRefs
const state = reactive({a: 1, b: 2})
const stateRefs = toRefs(state)
/*
stateRefs: not a proxy
{
a: {value: ...},
b: {value: ...}
}
*/
应用
setup() {
const state = reactive({a: 1, b: 2})
return {
...state // a,b不再是响应式
}
}
setup() {
const state = reactive({a: 1, b: 2})
return {
...toRefs(state) // a,b是响应式
}
}