背景:vue组件化是它的特点,经常定义组件的我们会知道把组件的data定义为函数,也知道是为了避免数据污染,而根实例则没有强制要求(因为根实例是单例,不用担心数据污染),具体原因是什么呢?我们也从源码来做分析吧,详见源码:src/core/instance/state.js中的initData()方法,当然我们也用demo来说明,demo如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vue data</title>
</head>
<body>
<div>vue组件data为什么必须是个函数而Vue的根实例则没有限制?源码中详见:src/core/instance/state.js中的initData()</div>
<div id="demo">
<div>vue组件data为什么必须是个函数?</div>
<comp></comp>
<comp></comp>
<div>{{counter}}</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
Vue.component('comp',{
template:'<div @click="counter++">{{counter}}</div>',
// data: {counter: 0}如果这么定义首先会报错,要求data为函数,原因是为了避免多个组件数据互相影响,造成数据污染,一会从源码中解释
data () {
return {
counter:1
}
}
})
//创建实例
const app = new Vue({
el: '#demo',
data:{counter:1}
});
console.log(app.$options.render);
</script>
</body>
</html>
1.源码解释组件data必须为函数的原因如下:
由上可以看出,如果是组件不采用函数会造成数据公用的情况,造成数据污染。
2.刚才也说过根组件data没有限制,一是因为const app = new Vue({el:'#demo'})是单例,另外也可以从源码中分析如下:/src/core/instance/init.js
通过给mergeoptions加断点发现,自定义组建会先执行,然后走根组件,源码位置:/src/core/util/options.js,具体详见合并策略,如下:
由上可以看出,当走自定义组件时vm不存在才走判断,如果当根组件实例创建之后就不会走条件检测了,所以根组件中data不用定义为函数。
综上得出以下结论:
vue组件可能存在多个实例,直接使用对象的形式定义data,会导致组件共用一个data对象,状态变更会影响所有的组件实例,这是不合理的。采用函数的形式,在initData时会将其作为工厂函数返回全新的data对象,避免了实例之间状态污染的问题。而vue根实例创建过程中不存在该限制,是因为根实例只有一个不需要担心这个问题。
综上,说明了为什么vue的自定义组件的data需要定义为函数,而根实例则没有此限制的原因,希望对大家有所帮助,以上,谢谢。