
🌈个人主页:前端青山
🔥系列专栏:Vue篇
🔖人终将被年少不可得之物困其一生
依旧青山,本期给大家带来vue篇专栏内容:vue3-响应式函数
目录
如下代码:当点击执行changeFn函数,修改setup中定义的变量时,发现页面中的name和age的数据并没有修改,说明该数据不是响应式数据
- <div>111div>
- <p>{{ name }}--{{ age }}p>
- <button @click="changeFn">changeFnbutton>
-
- export default {
- name: "App",
- setup() {
- //定义变量
- let name = "张三";
- let age = 20;
- // 定义方法
- function changeFn() {
- name = "李四";
- age = 30;
- }
- return {
- //setup函数返回值为一个对象
- name,
- age,
- changeFn,
- };
- },
- };
它是 vue3中的一个函数,一般用于将基本类型数据处理成响应式数据。
作用:定义一个基本类型的响应式的数据,只有数据成为响应式数据,这样当数据变化时,才能被监测到。
使用时需要从vue中引入
语法:const xxx =ref(数据变量);结果 返回一个 RefImpl 的引用对象,获取时为 xxx.value
在页面模板中使用数据直接 使用插值表达式,不需要加value
姓名:{{ name }}
,因为vue3会自动帮你.value,所以可以拿到值ref 函数实现数据响应式的原理还是利用了vue2的Object.defineProperty() 给数据设置 get set 监听函数,如下图:

接收的数据类型可以是基本类型(实现响应式原理为Object.defineProperty()),也可以是对象类型(当为对象时,实现响应式的原理就是Proxy不是Object.defineProperty())
点击如下change事件,修改name 和age
- <div>
-
- <p>{{ name }}--{{ age }}p>
- <p>{{ job.type }}--{{job.salary}}p>
- <p @click="change">说话p>
- div>
- <script>
- import { ref } from "vue"; // 引入响应式函数ref
- export default {
- name: "App",
- setup() {
- let name = ref("张三"); //返回一个 ref 引用对象
- let age = ref(20);
- console.log(name)
- // 当ref传的参数为对象时
- let job = ref({
- type: "前端工程师",
- salary: "20k",
- });
- function change() {
- name.value = "李四"; // ref对象.value 修改其值
- age.value = 30;
- job.value.type = "后端开发工程师";
- job.value.salary = "30k";
- }
- return {
- name,
- age,
- change,
- job
- };
- },
- };
- script>
1.定义一个对象类型的响应式数据,返回一个Proxy 实例对象,不能用于基本数据类型,否则报错。(基本类型响应式数据使用ref)。
语法:const 代理对象= reactive(源对象) ,接收一个对象或数组,返回一个代理对象(即Proxy源对象)
使用时先从vue中引入
- import { reactive } from "vue";
- ...
代码如下:
- <p>{{ job.type }} --{{ job.salary }}--{{ job.like.a.b }}--{{job.content}}p>
- <p v-for="(item, index) in foodArr" :key="index">{{ item }}p>
- <button @click="changeFn">changeFnbutton>
-
- import { reactive } from "vue";
- export default {
- name: "App",
- components: {},
- setup() {
- //定义对象
- let job = reactive({
- type: "前端工程师",
- salary: "20k",
- like:{
- a:{
- b:'不告诉你'
- }
- }
- });
- console.log(job);
- //定义数组
- let foodArr = reactive(["刷抖音", "敲代码"]);
- console.log(foodArr);
- // 定义方法
- function changeFn() {
- job.type = "后端开发工程师";
- job.salary = "30k";
- job.content = "写代码"; // 给对象添加属性
- foodArr[0]='买包包' // 通过下标修改数组
- }
- return {
- //setup函数返回值为一个对象
- job,
- changeFn,
- foodArr
- };
- },
- };
vue3中使用proxy 实现的数据响应去掉了vue2中不能检测到对象添加属性和通过下标修改数组而无法检测的情况。
1、数据定义角度对比:
ref用来定义:基本数据类型
reactive 用来定义: 对象或数组类型数据
注意:ref也可以定义对象或数组类型数据,它内部还是通过reactive转换成代理对象
2、原理角度对比:
ref通过Object.defineProperty() 的get和set 实现数据的响应式 即(数据劫持)
reactive 通过Proxy 实现数据响应式的,并通过Reflect 来操作源对象数据的。
3、从使用角度对比:
ref 定义的数据操作时需要使用 .value, 而插值表达式中使用时,不需要使用 .value
reactive 定义的数据操作都不需要 .value
对象数据新增属性和删除属性,不存在vue2.x 中的问题了。
- <div>
- <p>{{ person.name }}p>
- <p>{{ person.age }}p>
- <p>{{ person.sex }}p>
- <button @click="addSex">添加属性button>
- <button @click="deleteSex">删除属性button>
- div>
-
- import { reactive } from "vue";
- export default {
- name: "App",
- components: {},
- setup() {
- let person = reactive({
- name: "张三",
- age: 20,
- });
- console.log(person);
- //定义添加属性
- function addSex() {
- person.sex = "男";
- console.log(person);
- }
- // 定义删除属性
- function deleteSex() {
- delete person.sex;
- console.log(person);
- }
- return {
- person,
- addSex,
- deleteSex,
- };
- },
- };
数组数据直接通过修改下标,修改数组,不存在vue2.x 中的问题了。
- <div>
- <p v-for="(item, index) in person.like" :key="index">{{ item }}p>
- <button @click="change">修改数组的值button>
- div>
-
- import { reactive } from "vue";
- export default {
- name: "App",
- components: {},
- setup() {
- let person = reactive({
- name: "张三",
- age: 20,
- like: ["打球", "敲代码"],
- });
- console.log(person); // proxy 实例对象
- function change() {
- person.like[0] = "打台球";
- }
- return {
- person,
- change,
- };
- },
- };
首先说一下Reflect的作用。
- // Reflect是window下的一个内置对象
- // 1. 使用reflect 访问数据
- let obj = {
- name: '张三',
- age: 20
- }
- console.log(Reflect.get(obj, 'name')); // 张三
- // 2.使用Reflect 修改数据
- Reflect.set(obj, 'age', 50)
- console.log(obj);
-
- //3.使用Reflect删除数据
- Reflect.deleteProperty(obj, 'name')
- console.log(obj);
vue3响应原理代码:
通过Proxy代理,拦截对象中任意属性的变化,包括属性的读取,修改、设置、删除。
通过Reflect 反射对被代理对象的属性进行操作。
- let data = {
- name: "张三",
- age: 30
- }
- console.log(Proxy);
- // 使用p 对象代理data, Proxy为window 下的内置代理函数
- let p = new Proxy(data, {
- // 读取属性
- get(target, propName) {
- // target 就是 data
- console.log(`读取p上个${propName}属性`);
- return Reflect.get(target, propName)
- },
- // 修改和设置属性
- set(target, propName, value) {
- // value 为赋的值
- console.log(`修改p的${propName}属性`);
- // target[propName] = value
- Reflect.set(target, propName, value)
-
- },
- //删除属性
- deleteProperty(target, propName) {
- console.log(`删除p上的${propName}属性`);
- // return delete target[propName]
- return Reflect.deleteProperty(target, propName)
- }
- })