首页 > 文章列表 > Vue3中关于ref和reactive的问题怎么解决

Vue3中关于ref和reactive的问题怎么解决

reactive Vue3 ref
480 2023-05-10

Vue3中关于ref和reactive的问题怎么解决

    关于ref和reactive的问题

    如果你使用过 Vue3,你知道的,在 Vue3 中有两个非常常用的响应式 API:reactive 和 ref。它们会把我们想要追踪的数据变成响应式。

    而且我们在使用时一直被告知 ref 用于创建基础类型的响应式,也可以创建引用类型的响应式。而对于引用类型,底层也是转换为 reactive 来进行响应式处理。那既然这样为撒还需要 reactive ,全部使用 ref 不就行了吗?

    虽然 ref 创建的响应式数据在脚本中需要通过 .value 才能访问到呀!但是这里肯定影响不大。并且在模板中会自动添加上 .value,所以模板中不需要通过 .value 访问。

    既然这二者基本没撒差别,但是还是暴露了 reactive 这个 API,难道有什么场景是 reactive 能做而 ref 做不了的?

    简单了解 ref & reactive

    我们先简单了解一下这两个 API。

    reactive

    返回对象的响应式副本,响应式转换是“深层”的——它影响所有嵌套 property。我们一般这样写。

    const obj = reactive({ count: 0 })

    并且可以直接使用。

    const count = obj.count

    ref

    受一个内部值并返回一个响应式且可变的 ref 对象。ref 对象仅有一个 .value property,指向该内部值。我们一般是这样写。

    const data = ref(xxx)

    引用的时候,一般会通过data.value的方式引用。

    const dataValue = data.value

    通过跟踪 Vue3 的源代码可以证明,当我们调用 ref 方法来定义响应式数据时,当参数为对象类型时,其实里面用的是 reactive 方法。也就是说上面的 data.value ,事实上是 reactive 方法创造出来的。

    注意:

    reactive 能做的 ref 也能做,并且还是用 reactive 做的

    当 ref 的参数为对象时,用的就是 reactive 方法

    在 Vue3 中,如果是把对象类型的数据弄成响应式,reactive 和 ref 都可以,且ref 内部是通过r eactive 来支持的。也就是说,你 reactive 能做的,我 ref 也能做。

    简单来说 ref 是在 reactive 上在进行了封装进行了增强,所以在 Vue3 中 reactive 能做的,ref 也能做,reactive 不能做的,ref 也能做。

    个人理解ref是reactive的语法糖,如:ref(1) 就等价于 reactive({value: 1});

    平时项目ref一把梭,是可以的,问题也不大

    vue3 ref 和reactive的区别

    Ref

    ref数据响应式监听。ref 函数传入一个值作为参数,一般传入基本数据类型,返回一个基于该值的响应式Ref对象,该对象中的值一旦被改变和访问,都会被跟踪到,就像我们改写后的示例代码一样,通过修改 count.value 的值,可以触发模板的重新渲染,显示最新的值

    <template>
    
      
    
      <h2>{{name}}</h2>
    
      <h2>{{age}}</h2>
    
      <button @click="sayName">按钮</button>
    
    </template>
    
    
    
    <script lang="ts">
    
    import {ref,computed} from 'vue' 
    
    
    
    export default {
    
      name: 'App',
    
      setup(){
    
        const name = ref('zhangsan')
    
        const birthYear = ref(2000)
    
        const now = ref(2020)
    
        const age = computed(()=>{
    
          return now.value - birthYear.value
    
        })
    
        const sayName = () =>{
    
          name.value = 'I am ' + name.value
    
        }
    
        return {
    
          name,
    
          sayName,
    
          age
    
        }
    
      }
    
    }
    
    </script>

    reactive

    reactive是用来定义更加复杂的数据类型,但是定义后里面的变量取出来就不在是响应式Ref对象数据了

    所以需要用toRefs函数转化为响应式数据对象

    将上面用ref写的代码转化成reactive型的代码

    <template>
    
      <!-- <img alt="Vue logo" src="./assets/logo.png"> -->
    
      <div>
    
        <h2>{{ name }}</h2>
    
        <h2>{{ age }}</h2>
    
        <button @click="sayName">按钮</button>
    
      </div>
    
    </template>
    
    
    
    <script lang="ts">
    
    import { computed, reactive,toRefs } from "vue";
    
    
    
    interface DataProps {
    
      name: string;
    
      now: number;
    
      birthYear: number;
    
      age: number;
    
      sayName: () => void;
    
    }
    
    
    
    export default {
    
      name: "App",
    
      setup() {
    
       
    
    
    
        const data: DataProps = reactive({
    
          name: "zhangsan",
    
          birthYear: 2000,
    
          now: 2020,
    
          sayName: () => {
    
            console.log(1111);
    
            console.log(data.name);
    
            
    
            data.name = "I am " + data.name;
    
            console.log(data.name);
    
          },
    
          age: computed(() => {
    
            return data.now - data.birthYear;
    
          }),
    
        });
    
    
    
        const refData = toRefs(data)
    
        refData.age
    
        return {
    
          ...refData,
    
        };
    
      },
    
    };
    
    </script>
    
    
    
    <style>
    
    #app {
    
      font-family: Avenir, Helvetica, Arial, sans-serif;
    
      -webkit-font-smoothing: antialiased;
    
      -moz-osx-font-smoothing: grayscale;
    
      text-align: center;
    
      color: #2c3e50;
    
      margin-top: 60px;
    
    }
    
    </style>