搞懂vue3的ref、reactive、toRef、toRefs
首先需要明确这四个函数都是用于在 setup 中创造响应式变量的。
四个函数都需要从vue中导出: import {ref, reactive, toRef, toRefs} from 'vue'
总结:
reactive对比ref
从定义数据角度对比:
- ref用来定义基本类型数据
- reactive用来定义对象(或数组)类型数据
- 备注:ref也可以用来定义对象(或数组)类型数据,它内部会自动通过reactive转为代理对象;
从原理角度对比:
- ref通过Object.defineProperty()的get与set来实现响应式(数据劫持)
- reactive通过使用Proxy来实现响应式(数据劫持),并通过Reflect操作源对象内部的数据。
从使用角度对比
- ref定义的数据:js操作数据需要.value,模板中读取时不需要.value
- reactive定义的数据,操作与读取均不需要.value
toRef, toRefs
作用: 创建一个ref对象,其value值指向另一个对象中的某个属性
语法: const name = toRef(person, 'name')
应用: 要将响应式对象中的某个属性单独提供给外部使用时
扩展: toRefs与toRef功能一致,但可以批量创建多个ref对象,语法: toRefs(person)
分别举例:
ref使用
<template> <div class="demo"> <h2>姓名: {{name}}</h2> <h2>年龄: {{age}}</h2> <h3>岗位: {{job.type}}</h3> <h3>工龄: {{job.workingAge}}</h3> <button @click="updateInfo()">更新</button> </div> </template> <script lang="ts"> import { defineComponent, ref } from 'vue' export default defineComponent({ setup () { // 以下方式定义的是普通数据,非响应式数据 // let name = '张三'; // let age = 18; // let job = { // type: 'web前端', // workingAge: 8 // } // function updateInfo() { // name = '李四'; // age = 20; // console.log(name, age); // } // 基本类型:ref生成一个引用对象,通过get/set做数据劫持,Ref(reference引用)Impl(implement实现) let name = ref('张三'); let age = ref(18); console.log('name', name, age) // 对象类型,内部'求助'了vue3中的一个新函数reactive函数 let job = ref({ type: 'web前端', workingAge: 8 }) function updateInfo() { // 注:模板里面不需要使用.value,模板解析时遇到 ref对象会自动读取.value console.log(name, age); name.value = '李四'; age.value = 20; job.value.type = 'JAVA'; job.value.workingAge = 10; } return { name, age, updateInfo, job } } }) </script>
reactive:只用于创建引用类型数据的响应式,取值不用加.value return具体细节见代码注释
<template> <div class="demo"> <h2>姓名: {{name}}</h2> <h3>岗位: {{job.type}}</h3> <h3 v-show="job.workingAge">工龄: {{job.workingAge}}</h3> <h3 v-show="job.age">年龄:{{job.age}}</h3> <button @click="updateInfo()">更新</button> </div> </template> <script lang="ts"> import { defineComponent, ref, reactive } from 'vue' export default defineComponent({ setup () { let name = ref('张三'); let job: any = reactive({ type: 'web前端', workingAge: 8 }) console.log('job', job) function updateInfo() { name.value = '李四'; job.type = 'JAVA'; delete job.workingAge;// 删除工龄 job.age = 18; // 增加年龄 } // 返回一个对象(常用) return { name, job, updateInfo } } }) </script>
toRef和toRefs
setup () {
let person = reactive({
name: '张三',
job: {
j1: {
age: 18
}
}
})
// 下面是几种方式的不同点描述
return {
person, // 直接return出去,模板中使用不能直接使用name 需要 person.name,比较麻烦
name1: person.name, // 解构后模板中直接使用name,但是属性不再具有响应性
name2: toRef(person, 'name'), // 通过toRef来转变成ref对象
...toRefs(person), // 批量转换成ref对象
}
}