![]()
如图 ,data选项中声明了属性message,我们就可以通过app.message,或者在created,mounted,methods中定义的方法里通过 this.message来访问这个属性。
如此简单的就获取到了data选项中声明的属性,vue是怎么实现的呢?
![]()
当执行new Vue()时,底层执行了 this._init(options)方法,_init()方法通过 initMixin(Vue)绑定在Vue的原型上。
![]()
_init 方法中执行initState(vm)来处理我们在创建vue时声明的data等选项
![]()
如果我们声明了data选项,则调用initData(vm) 进一步处理
![]()
data选项有两种声明方式,可以直接声明为json对象,也可以声明为return json的function,这里data如果是一个function,则调用getData(data)进行处理。最终将data选项中声明的属性全部挂载到vm._data上。
![]()
![]()
遍历data选项中声明的所有属性,判断每个属性key是否在props或者methods中有同款,如果有,则发出警告,没有,则调用 proxy(vm, `_data`, key)
![]()
方法proxy中使用object.defineProperty给vue添加了新属性,并定义了该属性的get set方法,当我们通过app.message 或者 this.message时,触发的是绑定在vue对象上message属性的get方法。返回值是 this[sourceKey][key],也就是 this._data.message。之前data中的所有属性已经绑定在了_data上,所以就成功通过this._data.message拿到了值 hello vue。
说到这里,大家就明白了为什么我们可以通过这样或那样的方式访问data中声明的属性!
![]()
补充:
Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
语法:
Object.defineProperty(obj, prop, descriptor)、
参数:
obj
要定义属性的对象。
prop
要定义或修改的属性的名称或 Symbol 。
descriptor
要定义或修改的属性描述符。
描述符中我们重点说明get 跟 set
get
属性的 getter 函数,如果没有 getter,则为 undefined。当访问该属性时,会调用此函数。执行时不传入任何参数,但是会传入 this 对象(由于继承关系,这里的this并不一定是定义该属性的对象)。该函数的返回值会被用作属性的值。
默认为 undefined。
set
属性的 setter 函数,如果没有 setter,则为 undefined。当属性值被修改时,会调用此函数。该方法接受一个参数(也就是被赋予的新值),会传入赋值时的 this 对象。
默认为 undefined。