详解Vue中的ref和reactive函数 | 青训营笔记
这是我参与「第四届青训营 」笔记创作活动的第9天
1. ref函数
- 作用:定义一个响应式的数据
- 语法: const xxx = ref(initValue)
- 创建一个包含响应式数据的引用对象 【引用实现的实例对象】 (RefImpl对象【reference-implement】,简称ref 对象)。
- JS中操作数据:
xxx.value【在ref对象中可以看到value需要用getter】 - 模板中读取数据:不需要 .value,直接:
<div>{{xxx}}</div>【Vue3会自动解析到是ref对象,拿value值】
- 备注:
- 接收的数据可以是:基本类型、也可以是对象类型
- 基本类型的数据:响应式依然是靠Object.defineProperty()的get 与 set完成的
- 对象类型的数据:内部 “ 求助 ” 了Vue3.0中的一个新函数—— reactive函数 【封装了proxy的具体实现】
2. reactive函数
-
作用: 定义一个对象类型的响应式数据(基本类型不要用它,要用ref函数)
-
语法:const 代理对象= reactive(源对象)接收一个对象(或数组),返回一个代理对象(Proxy的实例对象,简称proxy对象) 【利用proxy可以实现响应式,getter / setter也可但启用es6的proxy】
-
reactive定义的响应式数据是“深层次的”。
-
内部基于 ES6 的 Proxy 实现,通过代理对象操作源对象内部数据进行操作。【且操作可以被Vue捕获 --> 数据劫持】
3. 具体的代码书写解析如下:
<script>
import { ref, reactive } from "vue";
export default {
name: "App",
setup() {
// 数据
let name = ref("张三"); // 使用数据劫持,捕获后根据逻辑更新页面【是ref对象,有getter和setter】
let age = ref(18);
let job = {
// 成为proxy代理对象而不是ref对象【es6的proxy】
type: "前端工程师",
salary: "30K",
a: {
b: {
c: "最深的",
},
},
};
let hobby = ["抽烟", "喝酒", "烫头"];
let job1 = ref(job); // ! 注意:这里ref和reactive都套住了同一个job,obj1改则obj2也会改,一同更新数据
let hobby1 = ref(hobby);
// let sex = reactive("female"); // 可以使用但会警告
let job2 = reactive(job);
let hobby2 = reactive(hobby);
function changeInfo() {
/**
* ? 0.直接改:
*/
console.log(name, age);
name = "小五";
age = 19; // 以这种方式无法更新数据并实现数据代理
/**
* ? 1. 用ref:
*/
console.log(name, age);
name.value = "李四";
age.value = 48; // 基本数据类型要加上value来改
console.log(job1.value); // 对象会转为proxy
job1.value.type = "UI设计师"; // 无需再加一层 .value
job1.value.salary = "60K";
/**
* ? 2. 用reactive:
*/
console.log(job2); // Proxy {type: 'UI设计师', salary: '60K', a: {…}} 'female'
// sex = "male"; // 修改不了
// sex.value = "male"; // 报错:读不到value属性
job2.type = "后端工程师";
job2.salary = "88k";
job2.a.b.c = "修改了的"; // 深层次的对象结构也可以检测到改动
/**
* ? 3. 检测数组改变:【reactive同样可以检测数组改变】
* * 且别于Vue2必须经过指定方法改变数据才可以达到响应式,Vue3中修改更简易
*/
hobby1[0] = "学习哦哈哈哈"; // 改不了
hobby2[0] = "学习哦哈哈哈"; // ! 有效,且一改则hobby、hobby1、hobby2都改
}
//返回一个对象(常用)
return {name,age,job1,job2,
// sex,
hobby, hobby1, hobby2, changeInfo,
};
},
};
</script>
3. reactive对比ref
一般用 reactive 比较多;一般会把基本数据类型封装到对象内 -> 用 reactive 定义对象类型
- 从定义数据角度对比:
- ref用来定义:基本类型数据。
- reactive用来定义:对象(或数组)类型数据。
- 备注:ref也可以用来定义对象(或数组)类型数据, 它内部会自动通过****reactive 转为代理对象。
- 从原理角度对比:
- ref通过Object.defineProperty() 的get与set来实现响应式(数据劫持)。
- reactive通过使用Proxy来实现响应式(数据劫持), 并通过Reflect操作源对象内部的数据。
- 从使用角度对比:
- ref 定义的数据:操作数据需要 .value,读取数据时模板中直接读取不需要 .value。
- reactive 定义的数据:操作数据与读取数据:均不需要 .value。