1、根实例对象data可以是对象,也可以是函数
因为根实例是单例,默认只有一个,不会产生数据污染情况
2、组件实例对象data必须为函数
在JS中,实例是通过构造函数创建出来的,每个构造函数可以new出多个实例,每个实例都会继承原型上的方法和属性。
而在Vue中,一个Vue组件就是一个Vue实例,当一个组件被复用多次,就会创建多个实例。如果data是对象,那么被多次复用的这个组件,在某一处改变了data数据,就会影响到其他处复用这个组件的地方。
因为对象是引用数据类型,是对于内存地址的引用,牵一发而动全身。
而如果data是一个函数的话,那么每次创建一个新的实例之后,就会调用这个新的data函数,返回一个新的对象。也就是给每一个data数据,定义了一个新的内存地址,自己维护自己的数据。
所以为了保证每个组件data的独立性,或者说是组件的可复用性,data就必须是一个函数。
总结:
目的是为了防止多个组件实例对象之间共用一个data,产生数据污染。所以需要通过工厂函数返回全新的 data 作为组件的独立数据源
注意:
Vue3中的data已经不存在对象的情况了,因为Vue3一切是从组件开始的,我们是通过createApp来创建应用,传递的参数就是我们的组件,所以组件中的data都是一个函数。
3、data是对象的情况下:
如下,data 是对象的情况下,会产生数据污染:
在我们定义好一个组件的时候,Vue
最终都会通过Vue.extend()
构成组件实例
function Vue() {
}
Vue.extend = function(options) {
function Sub() {
// 会将data存起来
this.data = this.constructor.options.data
}
Sub.options = options
return Sub
}
let Child = Vue.extend({
data: {
name: '组件默认的name'
}
})
// 两个组件就是两个实例,希望数据互不干扰
const component1 = new Child()
const component2 = new Child()
console.log(component1.data.name) // 组件默认的name
console.log(component2.data.name) // 组件默认的name
component1.data.name = '组件1更改默认的name'
console.log(component1.data.name) // 组件1更改默认的name
console.log(component2.data.name) // 组件1更改默认的name
4、data是函数的情况下:
通过工厂函数返回全新的 data 作为组件的独立数据源,就不会存在数据污染的情况。
function Vue() {
}
Vue.extend = function(options) {
function Sub() {
// 工厂函数返回全新的data作为组件的独立数据源
this.data = this.constructor.options.data()
}
Sub.options = options
return Sub
}
let Child = Vue.extend({
data() {
return {
name: '组件默认的name'
}
}
})
// 两个组件就是两个实例,希望数据互不干扰
const component1 = new Child()
const component2 = new Child()
console.log(component1.data.name) // 组件默认的name
console.log(component2.data.name) // 组件默认的name
component1.data.name = '组件1更改默认的name'
console.log(component1.data.name) // 组件1更改默认的name
console.log(component2.data.name) // 组件默认的name