这节课我们继续来学习reactive,上节课我们讲到reactive,那么reactive它其实只能用于对象类型 (对象、数组和如 Map
、Set
这样的引用类型。它不能用于 string
、number
、boolean
这些的基础类型,这些基本类型使用ref会更合适。
我们在使用reactive的时候,可能会觉得在模版用对象[属性]的方式来渲染数据会比较麻烦不舒服。所以很想把它进行解构了再渲染。
假设我们先按照我们自己的想法来进行尝试一下,我们把count解构出来再返回出去。
<template>
<button @click="increment">Count is: {{ count }}</button>
</template>
<script>
import {reactive} from 'vue'
export default {
setup(){
const state = reactive({count:0})
function increment() {
state.count++
}
//在这里进行解构
const { count } = state
return{
increment,
count
}
}
}
</script>
我们看一下这样解构能不能行,运行起来看一下效果。好,当运行之后我们来点击按钮时会发现没有了任何反应,count失去响应式功能。说明这样解构是不行,原因很简单大家应该一开始就知道的,state是一个响应式对象当我把它里面的count解构出来之后它变成了一个新的基础类型的变量,就相当于 count = 0。所以它就个普通的变量,是没有响应式效果的。
toRefs解构
上面我们尝试了解构reactive响应式对象,我们发现的根本行不同,那么如果非要解构它的话我们有什么办法呢。我们可以使用toRef API,用toRefs 先做个转化再来解构。
setup(){
const state = reactive({count:0})
function increment() {
state.count++
}
const { count } = toRefs(state)
return{
increment,
count
}
}
然后我们来运行看一下,点击按钮,这时候数据是会及时响应的。
toRefs,他会将一个响应式对象转换为一个普通对象,这个普通对象的每个属性都单独转换成了一个ref,就好比一个reactive响应式对象,被按属性拆分了多个ref,每一个ref都具有响应式功能。例如:
setup(){
const state = reactive({count:0})
function increment() {
state.count++
}
//state结构原本是这样的
proxy({count:0})
const { count } = toRefs(state)
//转化之后 变成了类似下面这个样子
{
count:ref(0) //==> proxy({value:0})
}
return{
increment,
count
}
}
这样大家应该就能理解了吧。我们给reactive再添加一个属性,它也是一样的。
const state = reactive({count:0,name:"老表"})
// state 原结构 proxy({count:0,name:"老表"})
const { count,name} = toRefs(state)
//被传化后
{
count:ref(0) //==>proxy({value:0}),
name:ref("老表") //==>proxy({value:"老表"})
}
使用这种toRefs帮助解构响应对象时,我们也可以直接放return这里来。
return{
...toRefs(state),
increment,
count
}
我们使用reactive 能创建出一个响应式对象,但是我们用 readonly可以将一个(响应式或普通)对象或 ref。转化成一个只读对象,只能读取不能修改,一修改就会报警告。
setup(){
const state = reactive({count:0})
const copyStae = readonly(state)
function increment() {
state.count++
copyStae.count++ //在这里修改它是会报错的
}
return{
...toRefs(state),
increment
}
}
![](file:///Volumes/WorkDisk/images/vue3/QQ20240321-011111.png?msec=1712157240788)
普通对象也是一样的,只要用它转化之后的对象都会变成只读的
const copyStae = readonly({name:"小红"})
function increment() {
state.count++
copyStae.name = "小明" //在这里修改它是会报错的
}