MVVM模型
1. Vue中的MVVM模型
其中View: 就是模版,和DOM对应。
Model:就是data, 和Plain JavaScript Objects(一般的js对象,js对象很多这里特指data)对应。
ViewModel: 主要是作为Model和View的桥梁,将Model通过数据绑定到模版上面,监听页面变化来处理Model数据变化, 简称为vm, 它本身就是Vue实例。
观察发现:
- data中的所有属性都出现在了vm身上。
- vm身上所有的属性以及Vue原型上的所有属性,在Vue模版中都可以直接使用。比如插值语法里面
{{$options}}
,{{$emit}}
,{{_c}}
。
观察控制台中Vue实例对象属性:
2. 数据代理
2.1 回顾ES6方法Object.defineproperty()
Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回这个对象。
语法为:Object.defineProperty(obj, prop, descriptor)
, 其中参数说明如下:
- obj: 要定义属性的对象。
- prop: 要定义或修改的属性的名称。
- descriptor: 将被定义或修改的属性描述符。属性描述符分为两种形式:数据描述符和存取描述符,且不能混合使用:
- 数据描述符:是一个具有值的属性,该值可以是可写的,也可以是不可写的。以下列举一些属性:
- configurable 值为true或false。只有值为true时,该属性的描述符才能改变,同时该属性也能从对应的对象上删除。默认值为 false。
- enumerable 值为true或false。只有值为true时,该属性为可枚举属性。默认值为false。
- value 包含了这个属性的数据值。默认值为undefined。
- writable 值为true或false。如果为true,属性的值,也就是上面的value,才能被改变。默认值为false。
- 存取描述符:是由getter-setter 函数对组成的属性。以下列举一些属性:
- configurable 值为true或false。只有值为true时该属性的描述符才能改变,同时该属性也能从对应的对象上删除。默认值为false。
- enumerable 值为true或false。只有值为true时,该属性为可枚举属性。默认值为false。
- get一个给属性提供getter的方法,如果没有getter则为undefined。该方法返回值被用作属性值。默认为undefined。
- set 一个给属性提供setter的方法,如果没有setter则为undefined。该方法将接受唯一参数,并将该参数的新值分配给该属性。默认为 undefined。
- 数据描述符:是一个具有值的属性,该值可以是可写的,也可以是不可写的。以下列举一些属性:
警告
在描述符中不能同时设置访问器(get和set)和数据属性(value和writable)。如果一个描述符已经设置了访问器,那么再设置value或writable会抛出TypeError异常。如果一个描述符已经设置了数据属性,那么再设置get或set也会抛出TypeError异常。
js
let person = {
name: 'test',
age: 18
}
Object.defineProperty(person, 'address', {
value: '成都市'
})
console.log(person)
不可枚举的意思就是不能参与遍历属性,比如:
js
console.log(Object.keys(person));
for(let key in person){
console.log(person[key])
}
js
Object.defineProperty(person, 'address', {
value: '成都市',
enumerable: true, // 控制属性是否可以枚举,默认为false
writable: true, // 控制属性是否可以被修改,默认为false
configurable: true // 控制属性是否可以被删除, 默认为false
})
虽然使用Object.defineProperty()添加属性比在data里面直接配置复杂一些,但能够更加灵活精细话控制属性。 以下是使用get/set函数实现:
js
let person = {
name: 'test',
age: 18
}
let myAddress = '地球'
let result = Object.defineProperty(person, 'address', {
// value: '成都市',
enumerable: true, // 控制属性是否可以枚举,默认为false
// writable: true, // 控制属性是否可以被修改,默认为false
configurable: true, // 控制属性是否可以被删除, 默认为false
// 当读取person的address属性时, get函数(getter)就会被调用,且返回值就是address的值
get:function getAddress(){
return 'hello'
},
/**
* 对象内部直接可以定义为get(){
}
**/
set(value){
myAddress = value
}
})
console.log(result)
3. 数据代理的理解
数据代理:通过一个对象代理对另外一个对象中属性的操作(读/写)
js
let obj={x:100}
let obj2={y:200}
Object.defineProperty(obj2, 'x', {
get(){
return obj.x
},
set(value){
obj.x = value
}
})
// 可以发现obj的x可以通过obj2来操作obj的x, 这就是一个数据代理
4. Vue中的数据代理
- Vue中的数据代理:通过vm对象来代理data对象中属性的操作(读/写)
- Vue中数据代理的好处:更加方便的操作data中的数据
- 基本原理:通过Object.defineProperty()把data对象中所有属性都添加到vm上去,为每一个添加到vm的属性都指定一个getter和setter方法,在getter/setter内部去操作(读/写)data中对应的属性。 特殊的说明下,虽然_data是Vue存放data原始数据的地方,但做了特殊处理: