入口
如果 option 中有 data,则调用 initData
,反之直接赋予 data 一个响应式的空对象initData
最终是还是会调用 observe(data, true)
,只不过加了一些前置校验及非法报错
// 数据初始化入口
if (opts.data) {
// initData 最终还是调用了 observe,只不过加了一些前置校验及非法报错
initData(vm)
} else {
observe(vm._data = {}, true /* asRootData */)
}
initData
- 将 data 转成实际对象
- 如果不是对象则非法报错,如果 props、methods 中已经定义了相关 key 值则非法报错
- props优先级 > methods优先级 > data优先级
- 添加访问代理
- 使数据具备响应式
function initData (vm: Component) {
// 将 Data 转成实际对象
let data = vm.$options.data
data = vm._data = typeof data === 'function'
? getData(data, vm)
: data || {}
if (!isPlainObject(data)) {
data = {}
process.env.NODE_ENV !== 'production' && warn(
'data functions should return an object:\n' +
'https://vuejs.org/v2/guide/components.html#data-Must-Be-a-Function',
vm
)
}
// 如果不是对象则非法报错,如果 props、methods 中已经定义了相关 key 值则非法报错
// 添加访问代理
// proxy data on instance
const keys = Object.keys(data)
const props = vm.$options.props
const methods = vm.$options.methods
let i = keys.length
while (i--) {
const key = keys[i]
if (process.env.NODE_ENV !== 'production') {
if (methods && hasOwn(methods, key)) {
warn(
`Method "${key}" has already been defined as a data property.`,
vm
)
}
}
if (props && hasOwn(props, key)) {
process.env.NODE_ENV !== 'production' && warn(
`The data property "${key}" is already declared as a prop. ` +
`Use prop default value instead.`,
vm
)
} else if (!isReserved(key)) {
proxy(vm, `_data`, key)
}
}
// 使 Data 具备响应式
// observe data
observe(data, true /* asRootData */)
}