7.4 initData
data
在初始化选项合并时会生成一个函数,只有在执行函数时才会返回真正的数据,所以initData
方法会先执行拿到组件的data
数据,并且会对对象每个属性的命名进行校验,保证不能和props,methods
重复。最后的核心方法是observe
,observe
方法是将数据对象标记为响应式对象,并对对象的每个属性进行响应式处理。与此同时,和props
的代理处理方式一样,proxy
会对data
做一层代理,直接通过vm.XXX
可以代理访问到vm._data
上挂载的对象属性。
function initData(vm) {
var data = vm.$options.data;
// 根实例时,data是一个对象,子组件的data是一个函数,其中getData会调用函数返回data对象
data = vm._data = typeof data === 'function'? getData(data, vm): data || {};
var keys = Object.keys(data);
var props = vm.$options.props;
var methods = vm.$options.methods;
var i = keys.length;
while (i--) {
var key = keys[i];
{
// 命名不能和方法重复
if (methods && hasOwn(methods, key)) {
warn(("Method \"" + key + "\" has already been defined as a data property."),vm);
}
}
// 命名不能和props重复
if (props && hasOwn(props, key)) {
warn("The data property \"" + key + "\" is already declared as a prop. " + "Use prop default value instead.",vm);
} else if (!isReserved(key)) {
// 数据代理,用户可直接通过vm实例返回data数据
proxy(vm, "_data", key);
}
}
// observe data
observe(data, true /* asRootData */);
}
最后讲讲observe
,observe
具体的行为是将数据对象添加一个不可枚举的属性__ob__
,标志对象是一个响应式对象,并且拿到每个对象的属性值,重写getter,setter
方法,使得每个属性值都是响应式数据。详细的代码我们后面分析。