当前位置: 首页 > news >正文

Vue3中的数据响应【4】

目录

  • 1.vue3中的数据响应:
      • 1.概述:
      • 2.使用:
        • 1.基本类型的数据:ref
          • 概述:
          • ref语法:
          • 案例演示:
          • 注意事项:
        • 2.对象类型数据:包括对象,数据,及嵌套对象
          • 概述:
          • reative语法:reative不能用在基本类型数据上
          • 示例:通过reative实现转变
          • 示例:通过ref实现对象类型数据的转变
      • 3.vue3中的数据响应失效:
        • 概述:
        • 案例:
        • 解决方案:
          • 方式1:通过ref创建对象类型数据
          • 方式2;通过Object的assign方法:
  • 4.toRef和toRefs函数:
      • 1.概述:
      • 2.案例:

1.vue3中的数据响应:

1.概述:

在vue3中,数据默认都是非响应式的(vue2默认为响应式),即修改数据后默认不会同步渲染到页面上;那么要如何将非响应式数据变成响应式呢,实际上在vue3中有两个函数ref和reative,可将默认的非响应式数据变成响应式;

2.使用:

1.基本类型的数据:ref
概述:
     在vue3中可以通过ref将基本类型的数据变成响应式;
ref语法:
 let 变量名=ref('初始值')  
案例演示:

我们还是以上面的案例来实现数据的响应式转变;

<template><h2>名称:{{ name }}</h2><h2 v-text="'地址:'+address"></h2><button @click="changeName">更新名称</button>
</template><!--setup  语法糖-->
<script lang="ts" setup name="School">import {ref} from "vue";let name =ref("猿究院") ;
let address = ref("北大街");
const changeName = () => {console.log("更新name属性:", name);name.value += "a";
}
</script><style scoped></style>    
   在此案例中,我们通过ref将数据name变成了响应式,然后我们在浏览器页面看一下是否实现了数据的同步渲染;

通过测试结果可以看出通过ref实现了数据的响应式转变;

我们再看一个案例:

<template><h2>姓名:{{name}}</h2><h2>年龄:{{age}}</h2><button @click="changeName">点击修改姓名</button><button @click="changeAge">点击修改年龄</button><button @click="showTel">点击展示联系方式</button>
</template><script lang="ts" setup name="Person">import {ref} from "vue";let name=ref('张三');let age=ref(25);let tel='122xxxxxxxx';const changeName=()=>{name.value+="a";}const changeAge=()=>{age.value++;}const showTel=()=>{alert("联系方式为"+tel);}
</script><style scoped></style>  
 此案例中我们还是通过ref将数据转变成响应式,再浏览器页面上依然可用看到数据的同步渲染

注意事项:

我们通过ref将基本类型数据转成响应式,不是说将数据本身转成了响应式;实际上通过ref函数得到的返回值为refimpl的实例对象,此对象有个value属性,此属性为响应式的,并且此属性指向我们转变的数据变量。其实我们通过打印转变后的数据也可以看出:因此修改数据时需要通过数据变量.value进行修改

2.对象类型数据:包括对象,数据,及嵌套对象
概述:

在vue3中我们通过reative或ref将对象类型数据转变成响应式数据;

reative语法:reative不能用在基本类型数据上
let 对象名=reative({属性1:值属性2:值
})  
示例:通过reative实现转变
<template><h2>汽车:{{Car.brand}}</h2><h2>价值:{{Car.price}}</h2><h2>游戏:</h2><ul><li v-for="item in games " :key="item.id">{{item.game}}</li></ul><h2>嵌套对象:{{obj.a.b.c.d}}</h2><button @click="changeCarBrand">点击修改汽车品牌</button><button @click="changeCarPrice">点击修改汽车价格</button><button @click="changeFirstGame">点击修改第一个游戏</button><button @click="changeObjValue">点击修改嵌套对象深层的属性值</button>
</template><script lang="ts" setup name="Car">
import {reactive, ref} from "vue";//对象数据let Car=reactive({brand:'奥迪',price:400000,})
//对象数组数据:let games=reactive([{id:'1001',game:'金铲铲',},{id:'1002',game:'云顶之弈',},{id:'1003',game:'英雄联盟',},])//嵌套对象数据let obj=reactive({a:{b:{c:{d:9999}}}})//回调函数const changeCarBrand=()=>{Car.brand='奔驰';}const changeCarPrice=()=>{Car.price+=10000;}const changeFirstGame=()=>{games[0].game='三星五费';
}const changeObjValue=()=>{obj.a.b.c.d+=100;
}
</script><style scoped></style> 

上述案例中,我们通过reative将对象类型的数据中的属性转成了响应式,包括对象类型数据的属性,数组类型数据的元素以及嵌套对象深层的属性,都可以将其转成响应式;但与ref不同的是,reative函数的返回值为proxy实例对象,此对象就是响应式的,并且此对象会代理指向原始需要转变响应式的对象,因此通过reative对对象类型数据进行修改时可以直接修改,而不需要像ref一样通过数据变量.value进行修改;

测试结果展示:

1.修改对象属性:

2.修改数组元素数据:

3.修改嵌套对象深层的属性:

示例:通过ref实现对象类型数据的转变
 ref不仅可以实现基本类型的数据转变,同时还支持对象类型数据的转变;实际上ref实现对象类型的转变本质上还是调用了reative函数来实现的;另外通过ref实现对象类型数据转变时,此对象如果是多层嵌套的对象(嵌套层数大于3层)时,就不推荐使用ref了,因为会降低执行效率;
<template><h2>汽车:{{Car.brand}}</h2><h2>价值:{{Car.price}}</h2><h2>游戏:</h2><ul><li v-for="item in games " :key="item.id">{{item.game}}</li></ul><h2>嵌套对象:{{obj.a.b.c.d}}</h2><button @click="ChangeCarBrand">点击修改汽车</button><button @click="ChangeCarPrice">点击修改汽车</button><button @click="changeFirstGame">点击修改第一个游戏</button><button @click="changeObjValue">点击修改嵌套对象深层的属性值</button>
</template><script lang="ts" setup name="Cars">
import {reactive, ref} from "vue";let Car=ref({brand:'奥迪',price:400000})
let games=ref([{id:'1001',game:'金铲铲',},{id:'1002',game:'云顶之弈',},{id:'1003',game:'英雄联盟',},
])//嵌套对象
let obj=ref({a:{b:{c:{d:9999}}}
})const ChangeCarBrand=()=>{Car.value.brand='宝马';}
const ChangeCarPrice=()=>{Car.value.price=660000;
}
const changeFirstGame=()=>{games.value[0].game='三星五费';
}const changeObjValue=()=>{obj.value.a.b.c.d+=100;
}
</script><style scoped></style>   

在上述案例中我们通过ref函数来改变对象类型数据为响应式,此时它的执行逻辑是这样的:当调用ref函数并传入一个对象类型数据时,首先会生成一个refimpl的对象,此对象中包含一个value属性,此属性的值即为原始的对象类型数据;之后vue3会再次调用reative函数生成一个proxy代理对象也指向原始的的对象类型数据,因此说ref改变对象类型数据为响应式本质上还是reative函数;

测试结果展示:

1.改变对象属性:

2.修改数组元素:

3.修改对象深层嵌套属性:

3.vue3中的数据响应失效:

概述:

在通过reative改变对象类型数据为响应式时,如果直接改变整个对象,而不是对象的某些属性,此时就会造成响应失效;

案例:
<template><h2>汽车:{{Car.brand}}</h2><h2>价值:{{Car.price}}</h2>
<button @click="changeCar">点击修改汽车(响应失效)</button>
</template><script lang="ts" setup name="Car">
import {reactive, ref} from "vue";let Car=reactive({brand:'奥迪',price:400000,})//响应失效const changeCar=()=>{Car={brand:'宝马',price:660000,}console.log(Car)}</script><style scoped></style> 
  在上述案例中,我们通过reative函数创建了一个原始对象类型的数据Car,然后通过单击事件直接改变Car对象,就会造成响应失效;其原因是因为:当使用 `reactive` 创建了 `Car` 对象后,`Car` 实际上是一个被 `Proxy` 包装的响应式对象。而这里将一个新的非响应式对象赋值给 `Car`,就破坏了原来的响应式引用。因此赋值后的Car对象就不再是一个响应式对象了,因此在修改此对象时,不会同步渲染到页面上;

解决方案:
方式1:通过ref创建对象类型数据
<template><h2>汽车:{{Car.brand}}</h2><h2>价值:{{Car.price}}</h2><button @click="changeCar">点击修改汽车(非响应失效)</button></template><script lang="ts" setup name="Car">
import {reactive, ref} from "vue";let Car=ref({brand:'奥迪',price:400000,})const changeCar=()=>{Car.value={brand:'宝马',price:660000}
}</script><style scoped></style> 

上述案例是通过ref函数来创建原始对象类型数据的,通过此种方式创建的对象是响应式的,并且在修改整个对象时,也不会造成响应失效;原因是因为:对于Car = ref({ brand: '奥迪', price: 400000 })Car是一个Ref类型的对象,其实际的数据存储在.value属性中,这个.value属性中的对象是被处理为响应式的;在changeCar函数中,Car.value = { brand: '宝马', price: 660000 }这样的操作是有效的。

因为Car是一个Ref对象,当修改其.value属性时,Vue 的响应式系统会将此视为数据的更新。它会触发组件的重新渲染过程,重新计算模板中的表达式(如{{Car.brand}}{{Car.price}})。在这里,虽然整个对象被替换了,但ref的响应式机制关注的是.value属性的变化,只要通过.value进行修改,它就能正确地通知相关的组件进行更新。

方式2;通过Object的assign方法:

此实现方式原理时将新旧对象的属性进行对比,将新对象中相同的属性的值修改到旧的对象上去,所以从本质上来说只是改变了对象的属性,并未改变对象类型数据本身;因此通过reative创建原始对象类型数据时,其代理对象proxy本身也没改变(只是代理对象的属性发生了改变),因此就不会造成响应失效;

<template><h2>汽车:{{Car.brand}}</h2><h2>价格:{{Car.price}}</h2><button @click="changeCar">点击修改汽车</button>
</template><script lang="ts" setup name="Carss">
import {reactive} from "vue";let Car=reactive({brand:'奥迪',price:400000,
})
const changeCar=()=>{Object.assign(Car,{brand:'宝马',price:660000})
}
</script><style scoped></style> 

上述案例中:通过reative函数创建了原始对象类型数据Car,并通过单击鼠标事件修改整个对象,在回调函数中,调用了Object的assign方法,将新对象的属性复制到原始对象中,对原始对象的属性进行修改,因为并没有直接覆盖原始对象,因此其代理对象proxy不会发生改变,因此也不会造成响应失效;

4.toRef和toRefs函数:

1.概述:

  • toRef函数用于创建一个对源响应式对象中某个属性的引用。它接受两个参数,第一个是源对象,第二个是要引用的属性名,通过此函数获取的对象的属性也为响应式(refimpl.value);
  • toRefs函数是将一个响应式对象的所有属性都转换为类似于toRef创建的引用。它接受一个响应式对象作为参数。

2.案例:

  <template><div class="person"><h2>姓名:{{ person.name }}</h2><h2>年龄:{{ person.age }}</h2><h2>性别:{{ person.gender }}</h2><button @click="changeName">修改名字</button><button @click="changeAge">修改年龄</button><button @click="changeGender">修改性别</button></div><div></div>
</template><script lang="ts" setup name="Person">import {reactive, ref, toRef, toRefs} from "vue";// ref  rea
let person = reactive({name: '张三', age: 25, gender: "男"});
//通过toRefs将person对象中的n个属性 批量的取出来
let {name, gender} = toRefs(person);
//通过toRef将person对象中的一个属性 取出来
// 转换为 RefImpl 实例对象
let age = toRef(person, 'age');const changeName = () => {name.value += '~';
}
const changeAge = () => {age.value += 1;console.log(age)
}
const changeGender = () => {gender.value = "女";
}</script><style scoped></style> 

上述案例中,我们通过reative创建了原始对象类型数据person,并通过toref函数和torefs函数取出了person对象的各个属性,由于取出的对象的属性也为响应式,因此我们可以对这些属性进行修改,并在页面实现同步渲染;


文章转载自:

http://7zvdX4rh.drbwh.cn
http://4EgYIxyJ.drbwh.cn
http://rgT9hcUD.drbwh.cn
http://SVMhCwGK.drbwh.cn
http://fHljifec.drbwh.cn
http://Wuusz2J4.drbwh.cn
http://AhfjSVRw.drbwh.cn
http://J8tj3wxn.drbwh.cn
http://syoFS3fB.drbwh.cn
http://lxwqeLiN.drbwh.cn
http://7T1qyb2P.drbwh.cn
http://RNytwGAh.drbwh.cn
http://siIurtIK.drbwh.cn
http://SNU7Dfg0.drbwh.cn
http://1gMWkyqh.drbwh.cn
http://IUIDj3gN.drbwh.cn
http://in4ha5ad.drbwh.cn
http://1xPuT4A8.drbwh.cn
http://jXqPS5LM.drbwh.cn
http://SVffeUIn.drbwh.cn
http://ih0Tksw6.drbwh.cn
http://ciABxszO.drbwh.cn
http://iSNePNLk.drbwh.cn
http://9m8CGEa0.drbwh.cn
http://bDFFAcpP.drbwh.cn
http://xPWvwiqd.drbwh.cn
http://CDAaYJXh.drbwh.cn
http://0Vs0EvD3.drbwh.cn
http://6ULuXUUo.drbwh.cn
http://Wdwx6nDQ.drbwh.cn
http://www.dtcms.com/a/368737.html

相关文章:

  • 因泰立科技:用激光雷达重塑智能工厂物流生态
  • 【Windows】通过 runas 命令实现多用户权限测试的完整流程
  • LangChain实战(十六):构建基于SQL数据库的数据分析Agent
  • Struts2 工作总结
  • 软件设计模式之单例模式
  • 小迪安全v2023学习笔记(七十八讲)—— 数据库安全RedisCouchDBH2database未授权CVE
  • 【Go】P2 Golang 常量与变量
  • Leetcode—721. 账户合并【中等】
  • Go初级之十:错误处理与程序健壮性
  • Go语言的编译和运行过程
  • Golang语言设计理念
  • Golang Goroutine 与 Channel:构建高效并发程序的基石
  • Golang中的context包介绍及源码阅读
  • 【JMeter】分布式集群压测
  • GEO 搜索引擎优化系统源码搭建与定制开发,支持OEM
  • Linux学习-硬件(串口通信)
  • 【蓝桥杯选拔赛真题65】C++求个数 第十四届蓝桥杯青少年创意编程大赛 算法思维 C++编程选拔赛真题解
  • AI美颜与瘦脸技术全解析
  • Dify on DMS,快速构建开箱即用的客服对话数据质检服务
  • 数字人打断对话的逻辑
  • Claude Code成本浪费严重?80%开支可省!Token黑洞解密与三层省钱攻略
  • 基于STM32的交通灯设计—紧急模式、可调时间
  • (未完待续...)如何编写一个用于构建python web项目镜像的dockerfile文件
  • OpenResty 和 Nginx 到底有啥区别?你真的了解吗!
  • c++ 第三方库与个人封装库
  • 好看的背景颜色 uniapp+小程序
  • 多目标粒子群优化(MOPSO)MATLAB
  • 【MySQL】mysql C/C++ connect
  • 设置静态IP的方法
  • 用得更顺手的 Protobuf 文件后缀、流式多消息、大数据集与“自描述消息”实战