Vue解疑之data属性为什么是函数
在Vue项目中,我们通常使用单文件组件和全局的component方法来定义组件,像下面这样:
Vue.component('test', {
data () {
return 'test'
}
})
但是,不管是使用单文件组件或是component的函数,我们发现组件options中的data是一个函数,并且返回了一个对象,为什么我们不直接用一个对象来赋值给data呢?
我们先来看下如果直接使用对象赋值给组件的data属性会发生什么?对于这个问题,Vue官网中给出了相应的回答:
当一个组件被定义,data 必须声明为返回一个初始数据对象的函数,因为组件可能被用来创建多个实例。如果 data 仍然是一个纯粹的对象,则所有的实例将共享引用同一个数据对象!通过提供 data 函数,每次创建一个新实例后,我们能够调用 data 函数,从而返回初始数据的一个全新副本数据对象。
有的人或许不太明白这段话是什么意思,下面我们来看一个例子。
// Test.vue
<template>
<div>
{{count}}
<button @click="add">add</button>
</div>
</template>
<script>
export default {
data: {
count: 1
},
methods: {
add () {
this.count++
}
}
}
</script>
// demo.vue
<template>
<div>
<Test></Test>
<Test></Test>
</div>
</template>
<script>
export default {
import Test from './Test.vue'
components: {
Test
}
}
</script>
我们在demo文件中引入了并使用了我们定义的data是对象的Test组件,效果如下图:
这时候我们点击下add按钮,会发现
两个组件的count值都变成了2,这个就是因为上面所说得的两个Test组件共享了data对象,所以导致当count变化时,两个组件的data同时更新。
这个问题出现的原因主要还是由于js引用类型的特殊性所致,在Vue创建组件的时候,是直接把创建组件的options进行传入,并没有做什么特殊操作,所以每个Test组件都一直保持着对同一个data对象的引用。所以要使用一个函数来返回一个对象以保证每个组件中的data都是独立的、唯一的。
其实Vue开发者也可以在创建组件的时候对options中的data进行一个深克隆来支持data是对象这个特性,但是深克隆对性能的消耗相对较大,不如直接与使用者约定好只能使用函数来定义data。