通过下面的代码例子分析这两个作用及其用法:
<template>
<h1>姓名:{{person.name}}</h1>
<h1>年龄:{{person.age}}</h1>
<h1>薪资:{{person.job.job1.salary}}w</h1>
<button @click="person.name+='~'">修改姓名</button>
<button @click="person.age++">修改年龄</button>
<button @click="person.job.job1.salary++">涨薪</button>
</template>
<script>
import { reactive } from 'vue'
export default {
name: 'Demo',
components: {},
setup() {
let person = reactive({
name: "sh",
age: 18,
job: {
salary: 10,
job1: {
salary: 20,
}
}
})
// 返回一个对象(常用)
return {
person
}
},
}
</script>
一、toRef
问题一:
我们观察一下下面代码,发现当嵌套多层次时,去使用数据的时候非常繁琐,怎么解决呢?
有人说,那我这样写。。
我在返回的时候直接定义好
用的时候就简洁多了、
问题二:
看下效果,这时候你会发现,点击操作的按钮的时候,数据不改变了,也就意味着,这样定义的数据丢失了响应式。。啊,这怎么回事
上面的写法就相当于,我们定义了一个属性age,取值是person.age,然后将其暴露出去。
点击修改年龄,发现age的数据改变,但视图并没有更新。看下结果:
说明我们上面的写法,age并不是响应式数据,打印一下看age是什么样子的
发现age就是一个字符串,并不具备响应式的条件。
Vue3的响应式
ref
也可以定义引用类型,框架会自动将对象或者数组转化为reactive
代理的对象ref
内部是通过value属性添加getter和setter来时间对数据的劫持reactive
是通过Proxy
来实现对对象内部所有数据的劫持
响应式数据是一个proxy对象,并不是一个字符串
这时候toRef就可以发挥他的作用了,他可以把你定义的name转为ref响应式数据。
toRef的使用
1.先引入
2.使用
toRef的使用
两个参数:第一个是你要转换的对象名称,第二个是你要转换的对象中属性的名称
看下结果:
注意:
所以这里我们就可以这样写:
看下结果,数据和视图都更新了。
问题三:那多层嵌套的怎么写呢?
有人说这么写,哈哈,跟我想法一样,但是这是不对的,他会把后面一整个都当成属性
下面这样才可以。说明第一个参数只要是个对象就行了。
问题四:有人说,你的目的不就是给他转为ref响应式吗,我直接转
这样写,效果虽然能实现,但是,,,修改的并不是person里面的数据,只是你复制出来的新的数据
我们来验证一下,把person显示在页面上。通过操作观察一下结果
通过以上操作发现,他们的数据并不同步。
改为toRef就正常了
总结:ref是对里面的属性复制出来一份。而toRef有引用关系,操作的就是其自身属性
二、toRefs
问题来了,当处理多个这种类型的数据时候
不能一直这么写吧
这时候toRefs就派上用场了
所以就是toRef是只能处理一个属性,toRefs就是可以批量处理多个属性~
toRefs如何处理多个,他只需要传入一个对象,就可以将里面所有属性都变成ref类型
这时候我们可以直接使用扩展运算符...toRefs(person)即可,将里面所有的属性都return出去。
...最终使用toRefs或者toRef的目的就是【简化模板中对复杂对象的使用的同时不失去响应式】