一、vue2响应式
1.实现原理
(1)对象类型
通过
Object.defineProperty()
对属性的读取、修改进行拦截(数据劫持)。
(2)数据类型
通过重写更新数组的一系列方法来实现拦截(对数组的变更方法进行了包裹)。
Object.defineProperty(data, 'count', {
get() {},
set() {}
})
2.模拟vue2中实现响应式
let person = {
name: 'Tom',
age: 18
}
let p = {}
Object.defineProperty(p, 'name', {
configurable: true, // 配置可被删除和新增(无法响应)
// 读取
get() {
console.log('读取操作响应')
return person.name
},
// 修改
set(value) {
console.log('修改操作响应')
person.name = value
}
})
Object.defineProperty(p, 'age', {
// 与上文name属性类似,这里省略
......
})
3.存在的问题
①新增属性、删除属性,界面不会更新。
②直接通过下标修改数组,界面不会自动更新。
二、vue3响应式
1.实现原理
(1)通过Proxy(代理)
通过Proxy拦截对象中任意属性的变化,包括:属性值的读写、属性的添加、属性的删除等。
(2)通过Reflect(反射)
通过Reflect对被代理对象的属性进行操作
2.模拟vue3中实现响应式
用到了Proxy代理对象和Reflect反射对象。
let person = {
name: 'Tom',
age: 18
}
// 让p映射对person的操作
const p = new Proxy(person, {
// 读取、新增
get(target, propName) {
console.log('读取或新增操作响应')
// return target[propName]
return Reflect.get(target, propName)
}
// 修改
set(target, propName, value) {
console.log('修改操作响应')
// target[propName] = value
Reflect.set(target, propName, value)
}
// 删除
deleteProperty(target, propName) {
console.log('删除操作响应')
// return delete target[propName]
return Reflect.deleteProperty(target, propName)
}
})
这个示例中,我们在Reflect对象之上有一行被注释的代码,这里没有用到Reflect,这样做更符合我们的直觉和常规用法,但是缺点就是不好捕获错误,得用到try-catch,这样铺列开来,就让底层源码有一堆的try-catch。用了Reflect对象来处理,就可以让封装框架更加健壮。
网友评论