咱们先参考vue官网给出的解释:vue
一个组件的
data
选项必须是一个函数,使得每一个实例能够维护一份被返回对象的独立的拷贝api
首先,咱们先看一个简单的原型链有关知识。markdown
`function VueComponent(){}
VueComponent.prototype.$options = {
data:{
name:'zf',
}
}
let vc1 = new VueComponent()
vc1.$options.data = 'lx'
let vc2 = new VueComponent()
console.log(vc2.$options.data)`
复制代码
咱们能够看到,实例对象VC1修改了name的值为“lx”,新的实例对象VC2访问到的值也是修改后的“lx”。函数
这是由于VC1和VC2两个实例对象在操做$options时是在操做VueComponent构造函数原型对象上的属性,实例对象的隐式原型属性等于其构造函数的显示原型属性,因此它们指向的是同一块内存空间。 这致使了两个对象数据不独立,会相互污染。spa
根据以上结果,再回到咱们Vue组件中的data属性。prototype
同一个组件被复用屡次,会建立多个实例。这些实例用的是同一个构造函数,若是 data 是一个对象的话,那么全部组件都共享了同一个对象。为了保证组件的数据独立性要求每一个组件必须经过 data 函数返回一个对象做为组件的状态。code
core/global-api/extend.js line:33
component
Sub.options = mergeOptions(Super.options, extendOptions)
function mergeOptions() {
function mergeField(key) {
const strat = strats[key] || defaultStrat options[key] = strat(parent[key], child[key], vm, key)
}
}
strats.data = function(parentVal: any, childVal: any, vm ? : Component
): ? Function {
if (!vm) { // 合并是会判断子类的data必须是一个函数
if (childVal && typeof childVal !== 'function') {
process.env.NODE_ENV !== 'production' && warn('The "data" option should be a function ' +
'that returns a per-instance value in component ' + 'definitions.', vm) return parentVal
}
return mergeDataOrFn(parentVal, childVal)
}
return mergeDataOrFn(parentVal, childVal, vm)
}
复制代码
一个组件被使用屡次,用的都是同一个构造函数。为了保证组件的不一样的实例data不冲突,组件中的数据相互 独立,要求data必须是一个函数,这样组件间不会相互影响。orm