🌈个人主页:前端青山
🔥系列专栏:Vue篇
🔖人终将被年少不可得之物困其一生
依旧青山,本期给大家带来vue篇专栏内容:vue3-响应式函数
目录
ref 响应式函数
引言:
ref 函数
reactive 函数
Reactive 与 ref 对比
vue3响应式原理
1、vue3响应式原理
ref 响应式函数
引言:
如下代码:当点击执行changeFn函数,修改setup中定义的变量时,发现页面中的name和age的数据并没有修改,说明该数据不是响应式数据
<template><div>111</div><p>{{ name }}--{{ age }}</p><button @click="changeFn">changeFn</button>
</template>
<script>
export default {name: "App",setup() {//定义变量let name = "张三";let age = 20;// 定义方法function changeFn() {name = "李四";age = 30;}return {//setup函数返回值为一个对象name,age,changeFn,};},
};
</script>
ref 函数
-
它是 vue3中的一个函数,一般用于将基本类型数据处理成响应式数据。
-
作用:定义一个基本类型的响应式的数据,只有数据成为响应式数据,这样当数据变化时,才能被监测到。
-
使用时需要从vue中引入
-
语法:const xxx =ref(数据变量);结果 返回一个 RefImpl 的引用对象,获取时为 xxx.value
-
在页面模板中使用数据直接 使用插值表达式,不需要加value <p>姓名:{{ name }}</p>,因为vue3会自动帮你.value,所以可以拿到值
-
ref 函数实现数据响应式的原理还是利用了vue2的Object.defineProperty() 给数据设置 get set 监听函数,如下图:
-
接收的数据类型可以是基本类型(实现响应式原理为Object.defineProperty()),也可以是对象类型(当为对象时,实现响应式的原理就是Proxy不是Object.defineProperty())
点击如下change事件,修改name 和age
<template><div><!--name这个ref 引用对象在使用时不需要加value,vue3会自动帮你加value,所以可以拿到值--><p>{{ name }}--{{ age }}</p><p>{{ job.type }}--{{job.salary}}</p><p @click="change">说话</p></div>
</template>
<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>
reactive 函数
1.定义一个对象类型的响应式数据,返回一个Proxy 实例对象,不能用于基本数据类型,否则报错。(基本类型响应式数据使用ref)。
语法:const 代理对象= reactive(源对象) ,接收一个对象或数组,返回一个代理对象(即Proxy源对象)
-
使用时先从vue中引入
<script>
import { reactive } from "vue";
...
</script>
-
代码如下:
<template><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">changeFn</button>
</template>
<script>
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};},
};
</script>
-
vue3中使用proxy 实现的数据响应去掉了vue2中不能检测到对象添加属性和通过下标修改数组而无法检测的情况。
Reactive 与 ref 对比
1、数据定义角度对比:
-
ref用来定义:基本数据类型
-
reactive 用来定义: 对象或数组类型数据
注意:ref也可以定义对象或数组类型数据,它内部还是通过reactive转换成代理对象
2、原理角度对比:
-
ref通过Object.defineProperty() 的get和set 实现数据的响应式 即(数据劫持)
-
reactive 通过Proxy 实现数据响应式的,并通过Reflect 来操作源对象数据的。
3、从使用角度对比:
-
ref 定义的数据操作时需要使用 .value, 而插值表达式中使用时,不需要使用 .value
-
reactive 定义的数据操作都不需要 .value
vue3响应式原理
-
对象数据新增属性和删除属性,不存在vue2.x 中的问题了。
<template><div><p>{{ person.name }}</p><p>{{ person.age }}</p><p>{{ person.sex }}</p><button @click="addSex">添加属性</button><button @click="deleteSex">删除属性</button></div>
</template>
<script>
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,};},
};
</script>
-
数组数据直接通过修改下标,修改数组,不存在vue2.x 中的问题了。
<template><div><p v-for="(item, index) in person.like" :key="index">{{ item }}</p><button @click="change">修改数组的值</button></div>
</template>
<script>
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,};},
};
</script>
1、vue3响应式原理
首先说一下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 就是 dataconsole.log(`读取p上个${propName}属性`);return Reflect.get(target, propName)},// 修改和设置属性set(target, propName, value) {// value 为赋的值console.log(`修改p的${propName}属性`);// target[propName] = valueReflect.set(target, propName, value)
},//删除属性deleteProperty(target, propName) {console.log(`删除p上的${propName}属性`);// return delete target[propName]return Reflect.deleteProperty(target, propName)}})