Vue2和Vue3的响应式原理区别
区分Vue2和Vue3的响应式原理
vue2的响应式原理
- 对象类型,通过object.defineProperty()对属性的读取,修改进行拦截——数据劫持
- 数组类型,通过重写更新数据的一系列方法来实现拦截,(对数组的变更方法进行拦截)
存在问题:
- 新增属性,删除属性,界面不会更新
- 直接通过下标修改数组,界面不会更新
新增解决方法:
- 1,通过this.$set(this.userinfo,‘name’,‘乞力马扎罗’)
- 2,import Vue from ‘vue’;
- Vue.set(this.userinfo,‘name’,‘乞力马扎罗’)
删除解决方法:
- 1,通过this.$delete(this.userinfo,‘name’,‘乞力马扎罗’)
- 2,import Vue from ‘vue’;
- Vue.delete(this.userinfo,‘name’,‘乞力马扎罗’)
数组下标修改不更新解决方法:
- 1,通过this.$set(this.list,0,‘乞力马扎罗’)
- 2,通过this.list.splice(0,1,‘乞力马扎罗’)
模拟vue2的响应过程
<script type="text/javascript">
let person = {
name: "乞力马扎罗",
age: "18",
};
//模拟Vue2中的响应式
let p = {
};
Object.defineProperties(p, "name", {
configurable:true,//可配置的,意味着可以删除了,但不是响应式,因为无法捕获是否删除key身上的一个属性
get() {
return person.name;
}, //读取name属性时,调用
set(value) {
person.name = value;
console.log("有人修改name,我该取更新界面了");
}, //修改name属性时,调用
});
Object.defineProperties(p, "age", {
get() {
}, //读取name属性时,调用
set(value) {
person.age = value;
console.log("有人修改nage,我该取更新界面了");
}, //修改name属性时,调用
});
</script>
vue3的响应式原理
模拟vue3的响应式原理
- 通过Proxy(代理)。拦截对象中任意属性的编号,包括属性值的读写,属性的添加,删除等
- 通过Reflect(反射)。对被代理的对象进行操作
代理
let person = {
name: "乞力马扎罗",
age: 18,
job: {
type: "前端",
salus: "30k",
},
list: [9],
};
//模拟Vue3实现响应式
//Proxy叫做代理,可以映射person,参数1是代理谁,参数2是必须写的,起码是空占位。里面存放进行的操作
const p = new Proxy(person, {
get(target, propName) {
//属性对象,属性
console.log("有人读取了target中的propName属性");
return target[propName];
},
set(target, propName, value) {
//属性对象,属性
console.log("有人修改、添加了target中的propName属性");
target[propName] = value;
},
deleteProperty(target, propName) {
console.log("有人删除了target中的propName属性");
return delete target[propName];
},
});
- Reflect修改被代理对象
反射
let person = {
name: "乞力马扎罗",
age: 18,
job: {
type: "前端",
salus: "30k",
},
list: [9],
};
//模拟Vue3实现响应式
//Proxy叫做代理,可以映射person,参数1是代理谁,参数2是必须写的,起码是空占位。里面存放进行的操作
const p = new Proxy(person, {
get(target, propName) {
//属性对象,属性
console.log("有人读取了target中的propName属性");
return Reflect.get(target[propName]);
},
set(target, propName, value) {
//属性对象,属性
console.log("有人修改、添加了target中的propName属性");
return Reflect.set(target, propName, value);
},
deleteProperty(target, propName) {
console.log("有人删除了target中的propName属性");
return Reflect.deleteProperty(target, propName);
},
});
- 通过reactive,内部就是先代理,后反射,即可删除,添加这 些,也会进行页面更新
<template>
<!-- VUE3组件中的模板结构可以没有根标签 -->
<h1>我是{
{
person.name }},我{
{
person.age }}</h1>
<h1 v-show="person.job">
我是{
{
person.job.type }},我{
{
person.job.salus }}
</h1>
<h1 v-show="person.size">我是{
{
person.size }}</h1>
<h1>我是{
{
person.list[0] }}</h1>
<button @click="sayword">点我更新信息</button>
<button @click="addsize">添加size</button>
<button @click="deljob">删除job</button>
</template>
<script>
import {
reactive, ref } from "vue";
export default {
name: "App",
setup() {
let person = reactive({
name: "乞力马扎罗",
age: 18,
job: {
type: "前端",
salus: "30k",
},
list: [9],
});
function sayword() {
console.log(person);
person.name = "罗曼蒂克";
person.list[0] = "罗曼蒂克";
}
//添加
function addsize() {
person.size = "超级大山";
}
//删除
function deljob() {
delete person.job.type;
}
return {
person,
addsize,
sayword,
deljob,
};
},
};
</script>
<style>
</style>