这是一篇普通大学生的学习记录帖,学习Vue3之前学过一些html,css,javascript的基础知识,希望可以通过记录博客对知识进行每日总结。 


目录

前言

一.ref创建基本类型的响应式数据

二.ref创建对象类型的响应式数据

三.ref和reactive的区别

1.ref既可以定义基本类型数据,也可以定义对象类型数据。reactive只可以定义对象类型数据。

2.返回对象不同(RefImpl对象和Proxy对象)

3.reactive重新分配一个新对象,会失去响应式(可以使用Object.assign去整体替换)

解决办法:使用Object.assign(target,sources)方法解决重新分配对象问题

总结:

最后


前言

上一篇中我们讲到setup里创建的数据不是响应式的,那么如何让数据变成响应式的呢?

这就是 ref() 函数的作用:定义响应式数据

ref 既可以定义基本类型的响应式数据(比如字符串,数字),也可以定义对象类型的响应式数据。还有一个函数reactive()也可以定义对象类型的响应式数据。但总的还是ref更重要一些,接下来我们讲讲ref()的使用。


一.ref创建基本类型的响应式数据

先从vue库中引用ref函数,再去使用。

语法:let 变量名 = ref("初始值"),把你想要变成响应式变量的初始值直接放到ref里,这个变量就变成响应式变量了!代码如下:

<template>
  <div class="person">
    <div>姓名:{{ name }}</div>    //在模板里直接用name,无需.value
    <div>年龄:{{ age }}</div>     //模板里的响应式数据自动给你.vale了
    <div>地址:{{ address }}</div>
  </div>
</template>

<script lang="ts" setup name='Person'>  
  import { ref } from 'vue';   //从库中引入ref函数
  let name = ref('图图');        //用ref创建响应式数据
  let age = ref('8');            //此时name,age是响应式数据
  let address = "翻斗花园";       //address不是响应式数据
  console.log(name);            //在控制台输出一下看看会得到什么信息
  console.log(age);             
  console.log(address);
  
  function changename() {
    name.value = '小黑';        //操作ref对象时需要.value
  }
</script>

从控制台输出我们可以看到他给我们返回了一个RefImpl的对象,这就是ref对象,而address没有使用ref,因此它只是一个普通变量。并且如果我们想要在JS中操作这个响应式数据,需要使用他的.value属性

对于let name = ref('图图')来说,name不是响应式的,name.value是响应式的。但在模板中不需要.value,直接使用即可。

二.ref创建对象类型的响应式数据

先从vue库中引用ref函数,再去使用。

和创建基本类型一样,使用 ref 直接包裹对象即可创建响应式数据。

 let car = ref({brand:'奔驰',price:'10'}); //定义响应式对象
 let games = ref([                          //定义响应式数组
    { id: 1, name: '英雄联盟' },
    { id: 2, name: '王者荣耀' },
    { id: 3, name: '原神' }
  ]);

此时,car和games 是一个响应式数据(ref 对象),其 .value 属性指向该对象。访问 / 修改对象属性时,需通过 .value 操作。

<template>
  <div class="person">
    <div>姓名:{{ name }}</div>
    <div>年龄:{{ age }}</div>
    //模板中同样不使用.value
    <div>{{ name }}的爱车:{{ car .brand}}, 价格:{{ car .price }}</div>
    <div>{{ name }}爱玩的游戏:</div>
    <button @click="changeGame">修改游戏</button>
    <button @click="changePrice">修改车价</button>
    <ul>
      <li v-for="game in games" :key="game.id"> {{ game.name }}</li>
    </ul>
    
  </div>
</template>

<script lang="ts" setup name='Person'>
  import { ref } from 'vue';
  let name = ref('图图');
  let age = ref('8');
  let car = ref({brand:'奔驰',price:10}); //定义响应式对象
  let games = ref([                      //定义响应式数组
    { id: 1, name: '英雄联盟' },
    { id: 2, name: '王者荣耀' },
    { id: 3, name: '原神' }
  ]);
 function changePrice(){
    car.value.price += 10     //JS中需要使用.value拿到对象里的响应式属性进行增改操作
  }
  function changeGame(){
    games.value[0].name = "贪吃蛇" //数组需要先拿到响应式属性再加索引下标
  } 
</script>

三.ref和reactive的区别

除了ref可以定义对象类型的响应式数据,还有一个函数reactive()也可以定义对象类型的响应式数据。如果ref接收的是对象类型,内部其实也是调用了reactive函数。

1.ref既可以定义基本类型数据,也可以定义对象类型数据。reactive只可以定义对象类型数据。

2.返回对象不同(RefImpl对象和Proxy对象)

当我们使用ref定义一个响应式对象,和用reactive定义一个响应式对象,他们在控制台返回的返回的对象其实是不同的。ref返回的是RefImpl对象,reactive返回的是Proxy对象。(Proxy 是 JavaScript 中一个强大的内置对象,用于创建一个对象的代理。)

图中可以看到,红色用ref创建的基本类型数据返回的是RefImpl对象,value值正常是8。黄色用reactive创建的对象类型数据返回的是Proxy对象。绿色用ref创建的对象类型的数据返回的虽然还是RefImpl,但value值是用的调用Proxy。

总结:ref 本质上会将对象类型数据自动转换为 reactive 代理对象(即 ref 内部通过 reactive 实现对象的响应式)。因此:

  • 对于对象类型,ref 和 reactive 的底层响应式机制一致(基于 Proxy),都能追踪对象属性的新增 / 删除 / 修改。
  • 但 ref 返回的是 Ref 对象(需通过 .value 访问),而 reactive 直接返回代理对象。

3.reactive重新分配一个新对象,会失去响应式(可以使用Object.assign去整体替换)

当我们用reactive创建一个响应式对象时,单独修改属性,这个属性是响应式的,但要给他重新分配一个对象(把他的属性值全部修改掉),他就不是响应式的了。在页面点击修改车的按钮页面无反应。

<script lang="ts" setup name='Person'>
  import { ref , reactive } from 'vue';
let car = reactive({brand:'奔驰',price:10}); //用reactive定义响应式对象
  function changeBrand(){
    car.brand = "宝马"   //修改对象属性值,是响应式的
  }
 function changePrice(){
    car.price += 10     //修改对象属性值,是响应式的
  }
  function changeCar(){
    car = {brand:'奥迪',price:20} //整体替换对象,不是响应式的
  }
</script>

解决办法:使用Object.assign(target,sources)方法解决重新分配对象问题

Object.assign(target,sources) 是 JavaScript 中用于合并对象的内置方法,它可以将一个或多个源对象的属性复制到目标对象,并返回合并后的目标对象。主要用于对象的浅拷贝或属性合并。

使用方法:当你要替换掉car整个对象属性,就把car放到target位置,把你要替换的属性放到sources位置:

function changeCar(){
    Object.assign(car, {brand:'奥迪',price:20}); //此时car对象引用未变,仍然是响应式的
  }

总结:

  • ref 既可以定义基本类型数据,也可以定义对象类型数据。
  • reactive 只可以定义对象类型数据,如果对象层级较深,就用reactive。
  • ref 创建的变量必须使用.value。
  • reactive 会重新分配一个对象,会失去响应式,使用Object.assign(target,sources)方法解决。

最后

如果这篇文章对你有帮助的话就点个赞吧!

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐