vue2.x的响应式
-
实现原理
- 对象类型:通过
Object.defineProperty()
对属性的读取、修改进行拦截(数据劫持) - 数组类型:通过重写更新数组的一系列方法来实现拦截(对数组的变更方法进行了包裹)
- 对象类型:通过
-
存在的问题
- 新增属性、删除属性 界面不会更新
- 直接通过下标修改数组 界面不会自动更新
// 源数据 let person = { name: '张三', age: 22 } let p = {} Object.defineProperty(p, 'name', { configurable: true, // 读取name时调用 get() { console.log('有人读取了name属性,我发现了,我要去更新界面!') return person.name }, // 修改name时调用 set(value) { console.log('有人修改了name属性,我发现了,我要去更新界面!') person.name = value } }) Object.defineProperty(p, 'age', { configurable: true, // 读取name时调用 get() { console.log('有人读取了name属性,我发现了,我要去更新界面!') return person.age }, // 修改name时调用 set(value) { console.log('有人修改了name属性,我发现了,我要去更新界面!') person.name = age } })
vue3.x的响应式
- 实现原理
-
通过Proxy(代理):拦截对象中任意属性的变化,包括:属性值的读写、添加删除等
-
通过Reflect(反射):对源对象的属性进行操作
-
MDN文档中描述的Proxy与Reflect:
- Proxy:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Proxy
- Reflect:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Reflect
// 源数据 let person = { name: '张三', age: 22 } const p = new Proxy(person, { // 有人读取p的某个属性时调用 get(target, propName) { console.log(`有人读取了p身上的${propName}属性`) return Reflect.get(target, propName) }, // 有人修改p的某个属性 或给p追加某个属性时调用 set(target, propName, value) { console.log(`有人修改了p身上的${propName}属性,我要去更新界面了!`) Reflect.set(target, propName, value); }, // 有人删除p的某个属性时调用 deleteProperty(target, propName) { console.log(`有人删除了p身上的${propName}属性,我要去更新界面了!`) return Reflect.deleteProperty(target, propName) } })
-