Open webVueBlog opened 4 years ago
注册组件的本质其实就是建立一个组件构造器的引用。使用组件才是真正创建一个组件实例。所以,注册组件其实并不产生新的组件类,但会产生一个可以用来实例化的新方式。
vue组件实例化后,同一组件不同的实例引用同一个data对象(函数)。
对于vue组件来说,要保证复用性,data必须是函数,返回一个对象,这样多个组件实例就能得到返回对象独立的拷贝。
对于vue根实例来说,因为只实例化一次,所以data可以是对象或函数
组件data为函数缘由
在创建或注册模板的时候传入一个 data 属性作为用来绑定的数据。但是在组件中,data必须是一个函数,因为每一个 vue 组件都是一个 vue 实例,通过 new Vue() 实例化,引用同一个对象,如果 data 直接是一个对象的话,那么一旦修改其中一个组件的数据,其他组件相同数据就会被改变,而 data 是函数的话,每个 vue 组件的 data 都因为函数有了自己的作用域,互不干扰。
在使用Vue开发的过程中,data这个options对于我们来说是最熟悉不过的了。一般来说我们的data通常会写成函数形式,通过return将数据返回,但是官方在以根实例编写demo的时候,我们发现他直接使用了对象的形式。
"data"选项应该是一个函数,并且在组件定义中返回每个实例的值。
从源码级别看一下,Vue中究竟做了什么处理。
在Vue根实例中data的使用
可以为函数,可以为对象
vue的实例的时候会调用一个init方法
function Vue (options) {
if (process.env.NODE_ENV!=='production'&& !(thisinstanceofVue)) {
warn('Vue is a constructor and should be called with the`new` keyword')
}
this._init(options)
}
// 在initData时候会先判断data的类型, 在根实例中无论是对象或者是函数类型均会解析
let data = vm.$options.data
data = vm._data = typeofdata === 'function'
? getData(data, vm)
: data || {}
在Vue组件中data的使用
只能为函数
vm.$options = mergeOptions(
resolveConstructorOptions(vm.constructor),
options|| {},
vm
)
strats.data = function (
parentVal:any,
childVal:any,
vm?:Component
):?Function {
if (!vm) {
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中的数据不会相互影响,从而避免数据污染。但由于根实例只有一个,所以不存在数据污染这种情况,也就可以使用对象了。
const MyComponents = function() {};
MyComponents.prototype.data = {
number:1
};
let component1 = newMyComponents();
let component2 = newMyComponents();
component1.data.number = 2
console.log(component1.data.number, 'component1-data') // 2
console.log(component2.data.number, 'component2-data') // 2
[vue]