入口

如果 option 中有 data,则调用 initData,反之直接赋予 data 一个响应式的空对象
initData 最终是还是会调用 observe(data, true),只不过加了一些前置校验及非法报错

  1. // 数据初始化入口
  2. if (opts.data) {
  3. // initData 最终还是调用了 observe,只不过加了一些前置校验及非法报错
  4. initData(vm)
  5. } else {
  6. observe(vm._data = {}, true /* asRootData */)
  7. }

initData

  1. 将 data 转成实际对象
  2. 如果不是对象则非法报错,如果 props、methods 中已经定义了相关 key 值则非法报错
    1. props优先级 > methods优先级 > data优先级
  3. 添加访问代理
  4. 使数据具备响应式
    1. function initData (vm: Component) {
    2. // 将 Data 转成实际对象
    3. let data = vm.$options.data
    4. data = vm._data = typeof data === 'function'
    5. ? getData(data, vm)
    6. : data || {}
    7. if (!isPlainObject(data)) {
    8. data = {}
    9. process.env.NODE_ENV !== 'production' && warn(
    10. 'data functions should return an object:\n' +
    11. 'https://vuejs.org/v2/guide/components.html#data-Must-Be-a-Function',
    12. vm
    13. )
    14. }
    15. // 如果不是对象则非法报错,如果 props、methods 中已经定义了相关 key 值则非法报错
    16. // 添加访问代理
    17. // proxy data on instance
    18. const keys = Object.keys(data)
    19. const props = vm.$options.props
    20. const methods = vm.$options.methods
    21. let i = keys.length
    22. while (i--) {
    23. const key = keys[i]
    24. if (process.env.NODE_ENV !== 'production') {
    25. if (methods && hasOwn(methods, key)) {
    26. warn(
    27. `Method "${key}" has already been defined as a data property.`,
    28. vm
    29. )
    30. }
    31. }
    32. if (props && hasOwn(props, key)) {
    33. process.env.NODE_ENV !== 'production' && warn(
    34. `The data property "${key}" is already declared as a prop. ` +
    35. `Use prop default value instead.`,
    36. vm
    37. )
    38. } else if (!isReserved(key)) {
    39. proxy(vm, `_data`, key)
    40. }
    41. }
    42. // 使 Data 具备响应式
    43. // observe data
    44. observe(data, true /* asRootData */)
    45. }