Vue.component()创建组件实例时,props的处理过程

74 阅读1分钟

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>`
})

注意,props最终没有和data放在一起