• 【vue3】toRef与toRefs的使用,toRef与ref的区别


    2024.1.20更新博客:
    更新内容:在工作中的实际应用示例,更新在文章最底部

    假期第四篇,对于基础的知识点,我感觉自己还是很薄弱的。
    趁着假期,再去复习一遍
    1、toRef与toRefs

    创建一个ref对象,其value值指向另一个对象中的某个属性
    语法:const name = toRef(person,‘name’)
    应用:要将响应式对象中的某个属性单独提供给外部使用时
    扩展:toRefs与toRef功能一致,但可以批量创建多个ref对象,语法:toRefs(person)

    示例:当定义penson为响应式对象时,再定义一个变量去接收对象中的某个值,
    const name1 = person.name 这种方式name1不具有响应式
    const name2 = toRef(person,‘name’) 这种方式name2具有响应式

    <template>
      <div>
        <h2>姓名:{{ person.name }}</h2>
        <h2>性别:{{ person.sex }}</h2>
        <h2>工作:{{ person.job.job1.work }}</h2>
        <button @click="person.name += '~'">姓名变了</button>
        <br />
        <button @click="person.sex += '!'">性别变了</button>
        <br />
        <button @click="person.job.job1.work += '还有其他工作'">工作变了</button>
      </div>
    </template>
    <script >
    import { ref, reactive,toRef } from "vue";
    export default {
      name: "demo",
      setup() {
        let person = reactive({
          name: "莲花",
          sex: "男",
          job: {
            job1: {
              work: "侦探",
            },
          },
        });
        const name1 = person.name;
        console.log(name1, "name1");
        const name2 = toRef(person,'name')
        console.log(name2, "name2");
    
        return {
          person,
        };
      },
    };
    </script>
    <style scoped></style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    在这里插入图片描述

    如果模板区想简化成这样

    <template>
      <div>
        <h2>姓名:{{ name }}</h2>
        <h2>性别:{{ sex }}</h2>
        <h2>工作:{{ work }}</h2>
        <button @click="name += '~'">姓名变了</button>
        <br />
        <button @click="sex += '!'">性别变了</button>
        <br />
        <button @click="work += '还有其他工作'">工作变了</button>
      </div>
    </template>
    <script >
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    就要用到toRef

    <script >
    import { ref, reactive, toRef } from "vue";
    export default {
      name: "demo",
      setup() {
        let person = reactive({
          name: "莲花",
          sex: "男",
          job: {
            job1: {
              work: "侦探",
            },
          },
        });
        const name1 = person.name;
        console.log(name1, "name1");
        const name2 = toRef(person, "name");
        console.log(name2, "name2");
    
        return {
        //toRef接收的第一个参数是对象,第二个是属性键
          name: toRef(person, "name"),
          sex: toRef(person, "sex"),
          work: toRef(person.job.job1, "work"),
        };
      },
    };
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    ref直接使用似乎也能达到相似的效果,但是可以替换为ref写法吗?答案是不可以
    在这里插入图片描述
    如果替换为ref的写法,只有在初始化的时候才会读取person中定义的属性,之后修改person中的属性,改的根本不是person中定义的属性,而是return中新定义出来ref包裹的属性。

    在模板区将person对象展示出来,然后点击三个按钮,看下打印出来的结果
    在这里插入图片描述
    三个按钮随意点击,页面已经变化了,但是person对象还是原来的
    在这里插入图片描述
    再换成toRef
    在这里插入图片描述
    person对象也一起发生了改变
    在这里插入图片描述

    toRef一次只能处理一个属性,toRefs可以批量处理一个对象中的所有属性
    …扩展运算符只能拿到第一层,所以模板区的work,从job开始往下点,job.job1.work
    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述

    toRef的本质是引用,保持住和源对象的连接关系,维持通话,进行一个桥接,
    toRef 创建的引用是对已有对象的属性的引用。因此,在修改 toRef 返回的引用时,会直接修改原始对象中的属性。

    ref的本质是拷贝,将对象中的属性读取出来,打包成一个新的ref,和原来的不再有连接关系。

    ref 适用于创建可变的单个值的响应式数据,而 toRef 用于获取已有响应式对象中特定属性的引用,并关注该属性的变化。

    2024.1.20更新:
    对于新知识的学习,初次接触概念性的东西,即使当下觉得自己理解了,但是很多时候的状态都是一学就会,一用就废。
    最能让我印象深刻的,都是在实际项目中的应用,当我遇到痛点,无法解决,在经历了磨人的解决过程后会发现,原来概念性的东西是因为遇到了什么问题,能去解决这样的问题,这个时候才能去理解原来是这么使用的,原来区别是这样的。

    1、假设有一个响应式的对象。

    <script lang="ts" setup>
    import { reactive } from "vue";
    const formData = reactive({
      name: "春夏",
      grade: "高三",
      age: 19,
      address: "尔滨冰雪大世界",
      gender: "2",
      describe: "品学兼优",
      animalYear: "龙",
      school: "尔滨第一高中",
    });
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    2、假设在页面中展示的时候不想写formData.name,formData.grade,formData.age,就想直接写name,grade,age(主要是隔太久了,具体的需求已经想不起来了,先说个简单点的演示下问题)

    <template>
      <div>{{ name }}-- {{ grade }}-- {{ age }}--</div>
     <button @click="gotoUniversity" style="width: 120px; background: skyblue"> 
    </template>
    <script lang="ts" setup>
    import { reactive } from "vue";
    const formData = reactive({
      name: "春夏",
      grade: "高三",
      age: 19,
      address: "尔滨冰雪大世界",
      gender: "2",
      describe: "品学兼优",
      animalYear: "龙",
      school: "尔滨第一高中",
    });
    let {name,grade,age} = formData 
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    页面中展示
    在这里插入图片描述
    点击去上大学按钮,改变formData 中的数据

    function gotoUniversity() {
    name = "秋冬";
    grade = "大学";
     age = 20;
      console.log(name,grade,age, "name,grade,age");
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    数据改变了但是页面没变
    在这里插入图片描述
    是因为let {name,grade,age} = formData 这一行代码相当于
    let name = formData .name
    let grade= formData .grade
    let age= formData .age

    formData 对象是响应式的,但是name ,age,grade相当于是自己定义的变量,不具有响应式。所以我们操作name ,age,grade的修改,只是在操作我们自己定义的变量,和formData 对象是没有关系的。

    要解决,就要用到toRefs,
    let {name,grade,age} =toRefs(formData )
    或者等价写法toRef
    let {name} =toRef(formData ,name)
    let {grade} =toRef(formData,grade )
    let {age} =toRef(formData,age )

    完整代码:

    <template>
      <div>{{ name }}-- {{ grade }}-- {{ age }}--</div>
      <button @click="gotoUniversity" style="width: 120px; background: skyblue">
        去上大学
      </button>
    </template>
    <script lang="ts" setup>
    import { reactive, toRefs } from "vue";
    let formData = reactive({
      name: "春夏",
      grade: "高三",
      age: 19,
      address: "尔滨冰雪大世界",
      gender: "2",
      describe: "品学兼优",
      animalYear: "龙",
      school: "尔滨第一高中",
    });
    
    let { name, grade, age } = toRefs(formData);
    
    function gotoUniversity() {
      name.value = "秋冬";
      grade.value = "大学";
      age.value = 20;
      console.log(name, grade, age, "name,grade,age");
    }
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    页面更新,打印的结果都是ref定义的响应式对象,所以赋值的时候别忘了加.value
    在这里插入图片描述

  • 相关阅读:
    京东店铺公司名爬虫
    python安装selselenium,chromedriver,秒杀脚本教程
    CS5266设计Typec转HDMI+PD+U2+U3四合一多功能拓展坞方案
    面试字节、美团、阿里等公司后,才知道软件测试面试题就这些...
    【算法】KMP算法——解决字符串匹配问题
    达观RPA实战-编码与解码
    Android14之java层:增加系统API(二百二十)
    装饰器模式——设计模式
    win10 修改MySQL8 wait_timeout 等超时和连接数配置
    攻防世界MISC练习区(gif 掀桌子 ext3 )
  • 原文地址:https://blog.csdn.net/weixin_49668076/article/details/133470288