Vue里面为什么data属性是一个函数而不是一个对象?

1,203 阅读2分钟

vue实例的时候定义的data属性既可以是一个函数也可以是对象,但是在组件中只能是一个函数。 一、vue实例

new Vue({
            el: '#app',
            //函数格式
            // data() {
            //     return {
            //         isShow1: false,
            //         isShow2: false
            //     }
            // },
            //对象格式
            data: {
                isShow1: false,
                isShow2: false
            },
})

如果组件当中定义为一个对象

Vue.component('component1', {
            template: `<div>组件1</div>`,
            data: {
                zb: 'zb'
            }
})

就会出现下面的警告: image.png

二、组件data定义函数与对象的区别

上面的我们说了data必须是一个函数所以这是为什么呢?

在我们定义好一个组件以后,vue都会通过Vue.extend()来构成组件实例,所以我们下面用构造函数来模拟实现一下;

function component(){
 
}

component.prototype.data = {
  num:0
}
const a = new component()
const b = new component()

//分别打印a.data.num的值和b.data.num的值
console.log(a.data.num) //0
a.data.count = 20
console.log(b.data.num) // 20


我们会发现修改了a组件里面的data的num值,b组件里面的data的num值也会发生改变。原因是两个公用了一个内存地址,a修改的内容,同样对b产生了影响。如果我们呢采用函数的形式就不会产生这样的影响(函数返回的对象内存地址不一样)

function component(){
 
}

component.prototype.data = function(){
  return {
   num:0
  }
}
const a = new component()
const b = new component()

//分别打印a.data.num的值和b.data.num的值
console.log(a.data.num) //0
a.data.count = 20
console.log(b.data.num) // 0

三、原理分析

vue源码里面的initData

image.png

这里显示data既可以是函数也可以是对象,为啥还会出现警告呢?

原因是组件在创建的时候,会进行选项的合并

在vue源码路径下/src/core/util/options.js

自定义组件会进入 mergeOptions进行选项合并

image.png

总结

跟实例对象data既可以是对象也可以是函数(跟实例是单例),不会产生数据污染,组件实例data必须是函数,目的是为了防止多个组件实例对象之间公用一个data,产生数据污染。采用函数的形式,initData调用时会将其作为工厂函数都会返回全新的data对象。