data属性

197 阅读1分钟

组件中

😶组件中的data为什么必须是函数

源码

src\core\instance\init.js L57 initState() => initData()

let data = vm.$options.data
data = vm._data = typeof data === 'function'
    ? getData(data, vm)
    : data || {}
  • 对象形式定义data时,多个组件中的data使用同一个对象,会造成数据污染
  • 函数形式定义data时,每次初始化执行函数返回新的数据对象,多组件互相不影响

根实例中

// 根实例中data可以为对象
new Vue({
    el: '#app',
    data: {
      foo: 'foo',
    },
})
  • 根实例只有一个,不需要担心数据污染问题

检测

在组件中对象形式定义data,运行时会检测报错
 <div id="demo">
    <h1>组件</h1>
    <comp></comp>
 </div>
 <script>
    Vue.component('comp', {
      template: '<div>I am a component</div>',
      data: {
        counter: 1,
      },
    })
    const app = new Vue({
      el: '#demo'
    })
 </script>

image.png

源码

src\core\util\options.js L121

// mergeOptions 时调用
strats.data = function (
  parentVal: any,
  childVal: any,
  vm?: Component
): ?Function {
  if (!vm) {
    if (childVal && typeof childVal !== 'function') {
      process.env.NODE_ENV !== 'production' && warn(
        'The "data" option should be a function ' +
        'that returns a per-instance value in component ' +
        'definitions.',
        vm
      )

      return parentVal
    }
    return mergeDataOrFn(parentVal, childVal)     // 1
  }

  return mergeDataOrFn(parentVal, childVal, vm)   // 2
}
  • 组件合并选项时还没有vm实例,所以会校验data是否为函数
  • 只有根实例创建时vm有值,会避开校验