J-DuYa / DY-Book

迁移知识点

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

vue 的 data 属性为什么是一个函数而不是一个对象?

J-DuYa opened this issue · comments

在 Vue2 版本中,组件中是不允许使用对象的方式定义 data 的,一旦用对象的方式定义 data 就会出现控制台报错的情况。

warn(
  'The "data" option should be a function ' +
    'that returns a per-instance value in component ' +
    'definitions.',
  vm
)

在根实例被创建的时候,可以是一个函数或者一个对象,源代码如下:

// core/instance/state.ts 128 行
function initData(vm: Component) {
  let data: any = vm.$options.data
  data = vm._data = isFunction(data) ? getData(data, vm) : data || {}
  if (!isPlainObject(data)) {
    data = {}
    __DEV__ &&
      warn(
        'data functions should return an object:\n' +
          'https://v2.vuejs.org/v2/guide/components.html#data-Must-Be-a-Function',
        vm
      )
  }
  // 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 (__DEV__) {
      if (methods && hasOwn(methods, key)) {
        warn(`Method "${key}" has already been defined as a data property.`, vm)
      }
    }
    if (props && hasOwn(props, key)) {
      __DEV__ &&
        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)
    }
  }
  // observe data
  const ob = observe(data)
  ob && ob.vmCount++
}

当我们创建组件的时候,会通过 Vue.extend 进行合并,如果是对象的话,多个组件的实例会操作合并后的 data 他们指向同一个引用地址,如果某个组件修改某一个属性,那么就是针对的就是公共数据,会影响到其他组件的正常使用。