• 【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
    在这里插入图片描述

  • 相关阅读:
    Servlet的使用手把手教学(一)
    c++11浅析
    lintcode 3605 · 二维网格偏移 【数组相关,模拟即可】
    一种多尺度协同变异的粒子群优化算法(Python代码实现)
    SQL的性能分析、优化
    eclipse中CheckStyle的安装和使用
    LLM——langchain 与阿里 DashScop (通义千问大模型) 和 DashVector(向量数据库) 结合使用总结
    【干活分享-年薪百万以上】Java高端人才应具备的能力
    《MATLAB 神经网络43个案例分析》:第32章 小波神经网络的时间序列预测——短时交通流量预测
    yapi以及gitlab的容器化部署
  • 原文地址:https://blog.csdn.net/weixin_49668076/article/details/133470288