首先需要明确这四个函数都是用于在 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对象
}
}