【vue高级】MVVM实现原理 第一篇 Object.defineProperty
【vue高级】MVVM实现原理 第二篇 数据劫持Observe
【vue高级】MVVM实现原理 第三篇 编译模板Compile
MVVM就是所谓的双向数据绑定,特点是数据影响视图,视图影响数据;经常用来作对比的有 angular 和 vue,angular 靠的是脏值检测,vue 靠的是数据劫持和发布订阅模式。
下面就来介绍一下 vue 的双向数据绑定是怎样实现的
Object.defineProperty
vue 使用的是 Object.defineProperty,顾名思义,是为对象定义属性
新增属性
先来为对象添加一个属性
let obj = {}
Object.defineProperty(obj, 'like', {
value: 'meat',
})
console.log(obj.like) // meat
删除属性
delete obj.like
console.log(obj.like) // meat
发现并没有删掉
因为 Object.defineProperty() 添加的属性默认是不可配置的(configurable为false),也就不可删除
设置configurable为true后就能正常删除
Object.defineProperty(obj, 'like', {
configurable: true,
value: 'meat',
})
delete obj.like
console.log(obj.like) // undefined
修改属性
obj.like = 'rice'
console.log(obj.like) // meat
发现属性值并没有被修改,修改失败。同理,因为writable默认为false
设置writable为true后就能正常修改
Object.defineProperty(obj, 'like', {
configurable: true,
writable: true,
value: 'meat',
})
obj.like = 'rice'
console.log(obj.like) // rice
遍历属性
for (let key in obj) {
console.log(key)
}
用常用的 for in 遍历对象属性,发现并没有打印出来想要的结果,这是因为这样添加的属性默认是不可枚举的(enumerable为false)
设置为 true 就好了
Object.defineProperty(obj, 'like', {
configurable: true,
writable: true,
enumerable: true,
value: 'meat',
})
for (let key in obj) {
console.log(key) // like
}
一般很少直接使用 value ,而是把 value 变为两部分,get() 和 set(),获取属性值用 get(),设置属性值用 set()
我们先来直接添加 get() 和 set() 试试:
Object.defineProperty(obj, 'like', {
configurable: true,
writable: true,
enumerable: true,
value: 'meat',
get() {
return 'meat'
},
set(val) {
console.log(val);
},
})
console.log(obj.like)
发现报错了
Uncaught TypeError: Invalid property descriptor. Cannot both specify accessors and a value or writable attribute
意思是说,有了 get() 和 set() 之后,就不能有 value 和 writable 了
删掉就好了
Object.defineProperty(obj, 'like', {
configurable: true,
enumerable: true,
get() {
return 'meat'
},
set(val) {
console.log(val);
},
})
console.log(obj.like) // meat
下一篇再讲如何实现数据劫持