Vue框架一个比较核心的功能就是我们的数据是响应式的,这样我们在修改数据的时候,页面会自动帮我们更新,那么想要实现这个功能就要实现对一个数据的劫持,即在取值和设置值的同时我们能够检测到即数据劫持。vue2响应式的实现原理所依赖的就是Object.defineProperty()这个API,而vue3用的则是proxy今天我就来分享一下这两个api。
Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象
Object.defineProperty(obj, prop, descriptor)
obj表示想要代理的对象
prop表示想要代理对象中的key
descriptor表示代理该对象的一些方法配置
我们在访问一个对象的某个值或者修改一个对象的某个值的时候会触发里边的getter和setter方法
let obj1 = {x: 100}let obj2 = {y: 200}Object.defineProperty(obj2, 'x', {get() {console.log('我读取了');return obj1.x},set(value) {console.log('我设置了');obj1.x = value}})console.log(obj2.x);obj2.x=111
执行结果:
configurable:false不能删除属性:
let Person = {name:'张三'};Object.defineProperty(Person, "name", {configurable: false,});console.log(delete Person.name);
当 writable 属性设置为 false 时,该属性被称为“不可写的”。它不能被重新赋值
Invalid property descriptor. Cannot both specify accessors and a value or writable attribute, #
enumerable设置为false定义了对象的属性是否可以在for…of以及for…in语句中枚举
configurable 特性表示对象的属性是否可以被删除,以及除 value 和 writable 特性外的其他特性是否可以被修改。
let person = {name: '张三',age: 18}
const p = new Proxy(person, {// 第一个参数是代理的对象,第二个参数是读取的属性名// 有人读取p的某个属性时调用get(target, propName) {console.log('有人读取了属性', target, propName);return Reflect.get(target[propName])},// 有人修改p的某个属性时或给p追加某个属性时调用set(target, propName, value) {console.log(`有人修改或新增${propName}属性,我要去修改页面了`);Reflect.set(target, propName, value)},// 有人删除p的某个属性是调用deleteProperty(target, propName) {console.log(`有人删除了属性${propName},我要去修改页面了`);return Reflect.deleteProperty(target, propName)// return delete target[propName]}})
这周也比较匆忙,原本想总结vue2响应式原理和vue3响应式原理的一些比较,但是现在自己了解的还不是很清楚,就先总结一下响应式原理背后所依赖的一些东西吧,等到之后了解清楚了再来分享。