开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第5天,点击查看活动详情
前言
上一章我们在分析代码时学习了Vue3的响应式数据,这一章我们一起来了解下响应式原理。
一、Vue2中的响应式
- 实现原理:
- 对象类型:通过Object.defineProperty()对属性的读取、修改进行拦截(数据劫持)。
- 数组类型:通过重写更新数组的一系列方法来实现拦截。(对数组的变更方法进行了包裹)
Object.defineProgerty(data, 'count', { get(){}, set(){} }) - 存在问题:
- 新增属性、删除属性,界面不会更新
- 直接通过下标修改数组,界面不会自动更新
- 解决方案
- 使用this.$set(this.person,'sex','女')或者Vue.set(this.person,'sex','女')添加属性,界面就能刷新了
- 使用this.$delete(this.person,'sex','女')或者Vue.delete(this.person,'sex','女')删除属性,界面就能刷新了
- 对于数组,也可以用this.和Vue.方法修改,如:this.$set(this.person.hobby,0,'学习'),第二个参数是数组下标
- 对于数组,数组上有个splice方法,用这个也可以解决,如:this.person.hobby.splice(0,1,'学习')
二、Vue3中的响应式
- 实现原理
- 通过Proxy(代理):拦截对象中任意属性的变化,包括:属性值的读写、属性的添加、属性的删除等。(在Vue3中主要感谢reactive,避免了Vue2上面提到的问题)
const person = { name:'张三', age:18 } const p = new Proxy(person,{ get(target,propName){ console.log('读取了属性'); return target[propName]; // 在操作源数据 }, set(target,propName,value){ console.log('修改或追加属性,将通知界面更新'); target[propName] = value; // 在操作源数据 }, deleteProperty(target,propName){ console.log('删除了属性,将通知界面更新'); return delete target[propName]; // 在操作源数据 } })- 通过Reflect(反射): 对源对象的属性进行操作。
const person = { name:"张三", age:18 } const p = new Proxy(person,{ get(target,propName){ console.log("读取了属性"); return Reflect.get(target,propName); }, set(target,propName,value){ console.log("修改了属性,将通知界面更新"); return Reflect.set(target,propName,value); }, deleteProperty(target,propName){ console.log("删除了属性,将通知界面更新"); return Reflect.deleteProperty(target,propName); } })- MDN文档中描述的Proxy与Reflect:
结束语
这一章我们学习了响应式,了解了响应式原理,下一章我们一起学习计算属性与监视。