vue源码如下(来自文件src/core/instance/index):
// src/core/instance/index
const dataDef = {}
dataDef.get = function () { return this._data }
const propsDef = {}
propsDef.get = function () { return this._props }
if (process.env.NODE_ENV !== 'production') {
dataDef.set = function () {
warn(
'Avoid replacing instance root $data. ' +
'Use nested data properties instead.',
this
)
}
propsDef.set = function () {
warn(`$props is readonly.`, this)
}
}
Object.defineProperty(Vue.prototype, '$data', dataDef)
Object.defineProperty(Vue.prototype, '$props', propsDef)
从这段代码来看,是将实例的_data对象进行代理,以遍可以直接用$data进行取值
那么为什么要将$data定义在vue的原型对象上,而不是实例上
没有深入研究。以下言论或许有误:
$data属性是在new Vue之前就已经定义好的
$data是在stateMixin函数中初始化的,而stateMixin是在Vue是初始化过程中调用的,在new之前,如果要把$data定义在实例上则需要在new Vue的时候去初始化,而其实并不需要这么麻烦,只要再原型上代理既可以,因为$data被定义为一个getter,实际上它仍然访问的是this._data。所以可以比较早的先初始化好这个getter。而且,这里Vue是用Object.defineProperty去初始化的,而这个有一个好处就是——实例上也有会这个属性.
举个例子
虽然属性定义在原型上,但是实例也是有的。