Decided to follow huang Yi teacher vue2 source course to learn the source of vue2, learning process, as far as possible output their income, improve learning efficiency, the level is limited, wrong words please correct ~

Clone the vue source code locally and switch to branch 2.6.

Introduction

Unknown Custom Element (vue) Unknown Custom Element (Vue) Unknown Custom Element (VUE)

There are two ways to register vUE:

  • Global registration
  • Local registration

To see a demo

There are two ways to register and use components:

<div id="app"></div>

<script src="/Users/zhm/mygit/vue/dist/vue.js"></script>
<script>
  / / child component
  let Hello = {
    name: "Hello".template: "<div>hello</div>"};// Global components
  let appComponent = {
    name: "app".// Registry component
    components: { Hello },
    // Use local components
    template: ` 
       
{{msg}}
`
.data: () = > ({ msg: "App" }), created() { console.log('Component of $options.components'.this.$options.components); }};// Register the global component Vue.component(appComponent.name, appComponent); console.log("Options.com ponents on Vue classes", Vue.options.components); // Root component instance let vueInstance = new Vue({ el: "#app".template: `<app></app>`});
</script> Copy the code

Take a look at the print:

To register global components, use Vue.com Ponent (name,componentOptions) to register local components using {components:{hello:hello}}

Register global component: Vue.com Ponent

See Vue.component how to define, do what, directly find a little difficult to find, directly paste source code:

InitAssetRegisters is register three properties on the Vue, components/filters/directives.

// src/core/global-api/assets.js

export function initAssetRegisters(Vue: GlobalAPI) {
  /** * Create asset registration methods. * ASSET_TYPES = [ 'component', 'directive', 'filter' ] */
  ASSET_TYPES.forEach((type) = > {
    Vue[type] = function (
      id: string,
      definition: Function | Object
    ) :Function | Object | void {
      if(! definition) {return this.options[type + "s"][id];
      } else {
        /* istanbul ignore if */
        if(process.env.NODE_ENV ! = ="production" && type === "component") {
          validateComponentName(id);
        }
        if (type === "component" && isPlainObject(definition)) {
          definition.name = definition.name || id;
          definition = this.options._base.extend(definition);
        }
        if (type === "directive" && typeof definition === "function") {
          definition = { bind: definition, update: definition };
        }
        this.options[type + "s"][id] = definition;
        returndefinition; }}; }); }Copy the code

Look at the source code skull pain place is, even if it is a simple function, but in order to consider the overall, it seems to feel more than a layer of window paper, vague, the content of the above simplification:

// component for cp
Vue.components = function (cpName, cpOptions) {
  // Make sure component has a name attribute on it
  cpOptions.name = cpOptions.name | cpName;
  // Vue. Extend turns cpOptions into a subclass of Vue.
  const cpClass = Vue.extend(cpOptions);
  // So the global component must be in Vue.options.components
  Vue.options.components[cpName] = cpClass;
  return cpClass;
};

Extend turns cpOptions into a Vue subclass, simplifying the code below
Vue.extend = function (cpOptions) {
  const Sub = function VueComponent(options) {
    this._init(options);
  };
  Sub.prototype = Object.create(Vue.prototype);
  // Different field merge strategies are different
  Sub.options = mergeOptions(Vue.options, cpOptions);
  return Sub;
};
Copy the code

Vue.options.components[cpName] = cpClass; Vue.options.components[cpName] = cpClass;

Using global components

Component classes have merged the Vue. The options on the options, and the component instantiation phase, will be executed again mergeOptions operation, incorporating VueComponent.options.com ponents to vm.$options.com ponents.

The _createElement method is then executed during the vNode creation process. Let’s review the logic of this section again. It is defined in SRC /core/vdom/create-element.js: SRC /core/vdom/create-element.js

export function _createElement (context: Component, tag? : string | Class<Component> |Function | Object, data? : VNodeData, children? : any, normalizationType? : number) :VNode | Array<VNode> {
  // ...
  let vnode, ns
  if (typeof tag === 'string') {
    let Ctor
    if (isDef(Ctor = resolveAsset(context.$options, 'components', tag))) {
      // component
      vnode = createComponent(Ctor, data, context, children, tag)
    }
}
Copy the code

This is how a vNode resolveAsset will find a Ctor based on the tag and then create a vNode resolveAsset based on the tag.

// src/core/utils/options.js
export function resolveAsset(
  options: Object, type: string, id: string, warnMissing? : boolean) :any {

  // Type is components or filters etc
  const assets = options[type];
  // id refers to the component name, or the component tag
  if (hasOwn(assets, id)) return assets[id];
  const camelizedId = camelize(id);
  // Hump form
  if (hasOwn(assets, camelizedId)) return assets[camelizedId];
  // Uppercase
  const PascalCaseId = capitalize(camelizedId);
  // It is a hyphen
  if (hasOwn(assets, PascalCaseId)) return assets[PascalCaseId];
  // fallback to prototype chain
  const res = assets[id] || assets[camelizedId] || assets[PascalCaseId];
  if(process.env.NODE_ENV ! = ="production"&& warnMissing && ! res) { warn("Failed to resolve " + type.slice(0, -1) + ":" + id, options);
  }
  return res;
}
Copy the code

I’m going to use id, I’m going to use hump ID, I’m going to use capital, I’m going to use hyphen, I’m going to use all three forms of ID, I’m going to return Ctor

Register local components

{hello} from the new component options. The mergeOptions must be merged into the new component’s vm.quarrels. Components. Get the corresponding Ctor from resolveAsset

Local components, of course, can only be used within components. Global components can be used by all components because Vue.options.com Ponents are merged into VM.options.com Ponents when the component is instantiated.

reference

  • Huang Yi teacher vuE2 source decryption course
  • Vue. Js technology revealed