由浅入深了解Vue组件中的data| 8月更文挑战

223 阅读1分钟

我们先参考vue官网给出的解释:

一个组件的 data 选项必须是一个函数使得每个实例可以维护一份被返回对象的独立的拷贝

首先,我们先看一个简单的原型链有关知识。

`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构造函数原型对象上的属性,实例对象的隐式原型属性等于其构造函数的显示原型属性,所以它们指向的是同一块内存空间。 这导致了两个对象数据不独立,会相互污染。

根据以上结果,再回到我们Vue组件中的data属性。

同一个组件被复用多次,会创建多个实例。这些实例用的是同一个构造函数,如果 data 是一个对象的话,那么所有组件都共享了同一个对象。为了保证组件的数据独立性要求每个组件必须通过 data 函数返回一个对象作为组件的状态。

core/global-api/extend.js line:33

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必须是一个函数,这样组件间不会相互影响。