为什么vue组件数据必须是函数?

vu8f3i0k  于 2023-02-19  发布在  Vue.js
关注(0)|答案(5)|浏览(133)

我正在阅读Vue components,发现他们对为什么数据需要成为函数的解释有些令人困惑:

根示例

var vm = new Vue({
  el: '#example',
  data: {
    message: 'here data is a property'
  }
})

一个组件

var vm = new Vue({
  el: '#example',
  data: function () {
     return {
       counter: 0
     }
  }
})

Vue文档通过为每个组件分配一个全局计数器变量来解释这种差异,然后他们对每个组件共享相同的数据感到惊讶......而且他们没有解释为什么他们已经在这里使用了一个函数。

var data = { counter: 0 }

Vue.component('simple-counter', {
  template: '<div>{{ counter }}</div >',
  data: function () {
    return data  
  }
})

当然,数据现在已共享

<simple-counter></simple-counter>
<simple-counter></simple-counter>
<simple-counter></simple-counter>

当引用全局对象作为数据源时,组件没有自己的数据就不足为奇了,对于将数据作为属性的根Vue示例也是如此。

var mydata = { counter: 0 }

var vm1 = new Vue({
  el: '#example1',
  data: mydata
})

var vm2 = new Vue({
  el: '#example2',
  data: mydata
})

所以我仍然有一个问题,为什么一个组件不能有一个数据属性?

ssm49v7z

ssm49v7z1#

据我所知,这是为了保存内存
很多框架,比如Angular 2或者React,都把组件的每个示例都做成一个单独的对象。这意味着每个组件需要的所有东西都被初始化了。不过通常情况下,你只需要在每次初始化时保持组件数据的独立性。方法和类似的东西保持不变。
Vue通过将数据作为返回对象的函数来避免这个缺陷。这允许单独的组件具有单独的内部状态,而不需要完全重新示例化整个组件。方法、计算属性定义和生命周期钩子只创建和存储一次,并针对组件的每个示例运行。
See this

iswrvxsc

iswrvxsc2#

data选项应该始终是组件上下文中返回新对象的函数。
这个预防措施是由vue制定的,所以无论何时你直接在data选项中定义对象,vue都会发现你犯了错误。
组件永远不允许直接改变它的状态,这可以防止我们在组件没有自己的状态的情况下搞砸和做坏事。
如果vue没有采取这种预防措施,那么您将有机会改变拥有该组件的任何其他组件,这将是一个安全问题。
文档中的示例:
不过,理解规则存在的原因还是很好的,所以让我们作弊吧。

<div id="example-2">
  <simple-counter></simple-counter>
  <simple-counter></simple-counter>
  <simple-counter></simple-counter>
</div>
var data = { counter: 0 }

Vue.component('simple-counter', {
  template: '<button v-on:click="counter += 1">{{ counter }}</button>',
  // data is technically a function, so Vue won't
  // complain, but we return the same object
  // reference for each component instance
  data: function () {
    return data
  }
})

new Vue({
  el: '#example-2'
})

因为所有三个组件示例共享同一个数据对象,所以增加一个计数器会增加所有的计数器!哎哟,让我们通过返回一个新的数据对象来解决这个问题:

data: function () {
  return {
    counter: 0
  }
}

现在我们所有的计数器都有自己的内部状态。

ttcibm8c

ttcibm8c3#

它必须是一个函数,因为否则数据将在组件的所有示例之间共享,因为对象是通过引用而不是通过值调用的。这不仅发生在引用全局对象时,也发生在数据本身就是对象时。如果数据是工厂-函数,返回一个对象。每次装入组件的新示例时,将从头开始创建此对象,而不是仅向其传递引用全球数据。

vsikbqxv

vsikbqxv4#

因为当Vue初始化数据时,

function initData(vm){

  let data = vm.$options.data

  data = vm._data = typeof data === ‘function’ ? getData(data, vm) : data || {}
   /*

     Because here,data is a reference from vm.$options.data, 
     if data is an object, 
     when there are many instances of this Component,
     they all use the same `data`

      if data is a function, Vue will use method getData( a wrapper to executing data function, adds some error handling)

      and return a new object, this object just belongs to current vm you are initializing

    */

   ……

  // observing data
  observe(data, true)

}
mec1mxoz

mec1mxoz5#

Vue强制data属性为函数的原因是组件的每个示例都应该有自己的数据对象。如果我们不这样做,所有示例将共享同一个对象,每次我们更改某个内容时,它都会反映在所有示例中。

var vm = new Vue({
  el: '#example',
  **data: function () {
     return {
       counter: 0
     }**
  }

相关问题