Vue2(Object.defineProperty)和Vue3(Proxy和Reflect)响应式原理
2023-12-13 16:00:36
Vue2和Vue3原理:
Vue2响应式实现原理:
对象类型:通过Object.defineProperty()对属性的读取、修改进行拦截(数据劫持)
数组类型:通过重写更新数组的一系列方法来实现拦截(对数组的变更方法进行了包裹)
Object.defineProperty(data, 'count', {
get() {},
set() {}
})
Vue2响应式存在问题:
新增属性、删除属性界面不会自动更新
直接通过下标修改数组,界面不会自动更新
具体案例用法如下:
<template>
<div>
<div>{{ obj.sex }}</div>
<div>{{ obj.arr }}</div>
<button @click="changeSex">sex</button>
<button @click="deleteSex">deleteSex</button>
<button @click="changeArr">arr</button>
</div>
</template>
<script>
import Vue from 'vue'
export default {
name: 'App',
data() {
return {
obj: {
name: '',
age: '',
arr: []
}
}
},
methods: {
changeSex() {
// 不能生效
// this.obj.sex = '男'
this.$set(this.obj, 'sex', '男') // 或者Vue.set(this.obj, 'sex', '男')
},
deleteSex() {
// 不能生效
// delete this.obj.sex
this.$delete(this.obj, 'sex')
},
changeArr() {
// 不能生效
// this.obj.arr[0] = '爱学习'
this.$set(this.obj.arr, 0, '1') // 或者使用this.obj.arr.splice(0, 1, '1')
this.$set(this.obj.arr, 1, '2') // 或者使用this.obj.arr.splice(1, 1, '2')
},
}
}
</script>
Vue3响应式实现原理:
通过Proxy(代理):拦截对象中任意属性的变化,包括:属性值的读写、添加、删除等
通过Reflect(反射):对被代理对象的属性进行操作
具体案例用法如下:
<template>
<div>{{ person.sex }}</div>
<div>{{ person.arr }}</div>
<button @click="changeSexAndArr">按钮</button>
</template>
<script>
import { reactive } from 'vue'
export default {
name: 'App',
setup() {
const person = reactive({
name: '张三',
age: 18,
job: {
industry: '前端',
salary: '30k'
},
arr: []
})
function changeSexAndArr() {
person.sex = '男'
person.arr[0] = 1
person.arr[1] = 2
setTimeout(() => {
delete person.arr
}, 2000);
}
return {
person,
changeSexAndArr
}
}
}
</script>
模拟Vue2和Vue3实现响应式原理
// person代表元对象。p代表代理对象
let person = {
name: '张三',
age: 18
}
// 模拟vue2实现响应式
//#region
// const p = {};
// Object.keys(person).forEach(item => {
// Object.defineProperty(p, item, {
// configurable: true, // true时使用delete才能删除对象的属性
// get() {
// return person[item]
// },
// set(value) {
// person[item] = value;
// }
// })
// })
//#endregion
// 模拟vue3实现响应式
const p = new Proxy(person, {
// 有人读取p的某个属性时调用
get(target, propName) {
// return target[propName]
// vue3使用的是Reflect,因为使用这个如果报错的话也不会导致代码执行不下去
return Reflect.get(target, propName)
},
// 有人修改p的某个属性,或给p追加某个属性时调用
set(target, propName, value) {
// target[propName] = value;
// vue3使用的是Reflect,因为使用这个如果报错的话也不会导致代码执行不下去
Reflect.set(target, propName, value)
},
// 有人删除p的某个属性时调用
deleteProperty(target, propName) {
// return delete target[propName]
// vue3使用的是Reflect,因为使用这个如果报错的话也不会导致代码执行不下去
return Reflect.deleteProperty(target, propName)
}
})
文章来源:https://blog.csdn.net/weixin_50236973/article/details/134949927
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!