Vue.component()创建组件实例时,props的处理过程
1、首先父组件挂载时,会通过子组件的类型type判断其是否是component
// 源码 在此方法内部:initAssetRegisters(Vue)
Vue[type] = function (id, definition) {
if (!definition) {
return this.options[type + 's'][id];
}
else {
if (type === 'component') {
validateComponentName(id);
}
if (type === 'component' && isPlainObject(definition)) {
definition.name = definition.name || id;
definition = this.options._base.extend(definition); // 进入此方法,将definition 标准化
}
if (type === 'directive' && isFunction(definition)) {
definition = { bind: definition, update: definition };
}
this.options[type + 's'][id] = definition;
return definition;
}
};
2、随后进入_base.extend(definition)方法,创建Sub对象,这个就是最终创建出来的组件实例
方法内部对definition进行包装,核心就是initProps()方法
function initProps(Comp) {
var props = Comp.options.props;
for (var key in props) {
proxy(Comp.prototype, "_props", key); // 这里使用ES5中的Object.defineProperty()
}
}
3、通过initProps()方法,组件上的props数据被代理(准确说应该是被定义到组件的原型上,也就是Sub的原型上)大家都知道,vue2和3状态的处理方式不一样
function proxy(target, sourceKey, key) { // target就是Sub = comp 的原型(就是组件本身)
sharedPropertyDefinition.get = function proxyGetter() {
return this[sourceKey][key];
};
sharedPropertyDefinition.set = function proxySetter(val) {
this[sourceKey][key] = val;
};
Object.defineProperty(target, key, sharedPropertyDefinition);
}
4、最后Vue.component()将组件实例抛出
let sub = Vue.component('sub', {
props: ['data'],
template: `<h1>{{ data }}</h1>`
})