_
2024/4/3 00:14:00545

ref和reactive响应式状态2

这节课我们继续来学习reactive,上节课我们讲到reactive,那么reactive它其实只能用于对象类型 (对象、数组和如 MapSet 这样的引用类型。它不能用于 stringnumber 、boolean 这些的基础类型,这些基本类型使用ref会更合适。

reactive解构问题

我们在使用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
 }
readonly只读代理

我们使用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 = "小明" //在这里修改它是会报错的
}