vue3.0 数据响应式原理的实现:
1: 实现原理:
通过(Proxy)代理实现: 拦截对象中任意属性的变化, 包括属性值的读写, 属性的添加, 属性的删除等操作。
2: 通过(Reflect)(反射); 被代理的对象, 属性进行操作。
MDN 文档中描述的Proxy 与Reflect:
new Proxy(data, {
// 拦截读取属性值
get (target, prop) {
return Reflect.get(target, prop);
},
// 拦截设置属性值或者添加属性值
set(target, prop, value) {
return Reflect.set(target, prop, value)
},
// 拦截删除删除属性
deleteProperty(target, prop) {
return reflect.deleteProperty(target, value);
}
})
vue3.0 中不存在vue2.0 中说的这些问题
在一个对象中新增, 删除, 修改属性, 界面不会自动更新。
直接通过下标修改数组, 界面不会自动更新。
vue2.0 中实现数据响应式原理:
let person {
name: "李明",
age: 18
}
// 模拟vue2.0 中实现响应式
let p = {};
Object.defineProperty(p, 'name', {
get() { // 有人读取name 属性调用
return person.name
},
set(value) { // 有人修改name 属性是调用
person.name = value
}
})
Object.defineProperty(p, 'age', {
get() { // 有人读取name 属性调用
return person.age
},
set(value) { // 有人修改name 属性是调用
person.age= value
}
})
Object.defindProperty(person, 'sex', {
value:"男", // 设置值
emnumable: true, // 可枚举的, 默认值为false
writeable: true, // 可以被修改的, 默认值为false
})
vue3.0 中proxy 就是代理的含义:
window 全局身上有一个proxy 代理对象:
const p = new proxy(person, {}), // 配置对象
对属性进行增删改查的操作proxy 都可以捕获到。
vue3.0 实现响应式的模拟:
const p = new proxy(person, {
// 有人读取p 身上的某个属性
get(target, propName) {
console.log(`有人读取了p身上的${propName}属性`, 更新界面);
return target[propName]; return 出去一个返回值
},
// 给p对象身上增加/ 修改某个属性时调用
set(target, propName, value) {
console.log(`有人修改/增加了p身上的${propName}属性`, 更新界面);
target[propName] = value;
},
deleteproperty(target, propName) {
console.log(`有人删除了p身上的${propName}属性`, 更新界面);
return delete target[propName]; // 删除一个属性
}
})
proxy 可以实现数据的增删改查
从对象中读取一个属性: 使用window 全局身上有一个Reflect(反射)
let object = {
a: 1,
b: 2
}
第一种: object.a = 1;
第二种: 使用window 全局身上有一个Reflect(反射) Reflect.get(object, a);
第一个参数要读取的对象, 第二个参数要读取对象的属性值
修改对象身上的某一个属性:
可以使用: object.a = 666; 直接拿到属性值进行修改。
第二种方法: object.set(obj, 'a', 666); // 第一个要修改的对象, 第二个参数要修改的属性名, 第
三个参数就是要修改的值。
删除对象中某个属性:
let object = {
name: "李明",
age: 18 // 年龄
}
删除对象某个属性, 使用delete 方法: delete.object.name 删除object 对象中name 属性。
Reflect.deleteProperty(object, a) 使用Reflect(反射) deleteProperty 删除对象身上属性。
对一个属性的基本操作, 体现不出来Reflect 的威力:
Reflect 身上也有definedProperty() 属性:
Reflect.defineProperty() 身上是有返回值的。 返回值是布尔值
Reflect 的使用在框架封装使用上好处:
Reflect 是一个内置对象, 它提供了可以拦截javaScript 操作方法。 方法与代理处理程序相同。 Reflect 不是一个对象, 因此它是不可以new 的, 不可以当做构造函数使用。
new Reflect() //错误的写法
Reflect提供了一些静态方法, 静态方法是指只能通过对象自身访问的的方法。
1、Reflect.apply()
2、Reflect.construct()
3、Reflect.defineProperty()
4、Reflect.deleteProperty()
5、Reflect.enumerate()
6、Reflect.get()
7、Reflect.getOwnPropertyDescriptor()
8、Reflect.getPrototypeOf()
9、Reflect.has()
10、Reflect.isExtensible()
11、Reflect.ownKeys()
12、Reflect.preventExtensions()
13、Reflect.set()
14、Reflect.setPrototypeOf()
静态方法的使用:
Reflect.get() 方法:
Rlflect.get() 获取目标对象指定的key的value.
let object = {
a:1,
}
let s1 = Reflect.get(obj, "a");
console.log(s1) ===>获取指定对象的属性名
vue3.0 实现响应式的实现:
const p = new proxy(person, {
// 有人读取p 身上的某个属性
get(target, propName) {
console.log(`有人读取了p身上的${propName}属性`, 更新界面);
return Reflect.get(target, propName) return 出去一个返回值
},
// 给p对象身上增加/ 修改某个属性时调用
set(target, propName, value) {
console.log(`有人修改/增加了p身上的${propName}属性`, 更新界面);
Reflect.set(target, propName, value)
},
deleteproperty(target, propName) {
console.log(`有人删除了p身上的${propName}属性`, 更新界面);
return Reflect.deleteProperty(target, value) // 删除一个属性
}
})
Proxy: 用到的是一个代理对象, Reflect: 反射对象 (对立的一面)