How are Vue components parsed and rendered?

How are Vue components parsed and rendered?

Preface

This article will explain how Vue components are parsed and rendered.

We can register global components through Vue.component and then use them in templates

<div id="app">
  <my-button></my-button>
</div>
<script>
 Vue.component("my-button", {
    template: "<button> Button component</button>",
   });
let vm = new Vue({
	el:'#app'
});
</script>

Global component parsing principle

In order to ensure the isolation of components, each component generates a new class through the extend method to inherit the parent class. And merge the opts passed by the user through the Vue.component method into vue.options.components, and then merge Vue.options.components and vm.$options.components when vue is initialized.

1. Vue.component method

Vue.options._base = Vue; //You can find vue through \_base
Vue.options.components = {}; 

Vue.component = function (id, definition) {
  //Each component generates a new class to inherit the father definition = this.options._base.extend(definition);

  console.log("1. Create a constructor for the component, based on Vue", definition);

  this.options.components[id] = definition;
 };

2. Vue.extend method

The extend method generates a class that inherits from Vue and should have all the functions of the parent class.

import {mergeOptions} from '../util/index'
Vue.extend = function (definition) {
  const Vue = this;
  const Sub = function VueComponent(options) {
   this._init(options);
  };
  Sub.prototype = Object.create(Vue.prototype);
  Sub.prototype.constructor = Sub;
  Sub.options = mergeOptions(Vue.options, definition); 
  return Sub;
 };

3. Attribute merging

Merge the definition passed in by Vue.options and Vue.component(definition)

strats.components = function (parentVal, childVal) {
 let options = Object.create(parentVal);
 if (childVal) {
  for (let key in childVal) {
   options[key] = childVal[key];
  }
 }
 return options;
};

4. Initialize the merge

Merge Vue.options.components and vm.$options.components

 Vue.prototype._init = function (options) {
  const vm = this;
 ++ vm.$options = mergeOptions(vm.constructor.options, options); 
  //...
  initState(vm);
  if (vm.$options.el) {
   //Mount the data onto this template vm.$mount(vm.$options.el);
  }
 };

Okay, here we have implemented the parsing of global components.

Next, let’s take a look at how the Kang Kang component is rendered.

Component rendering principle

When creating a virtual node, we need to use isReservedTag to determine whether the current tag is a component. The virtual node of a common tag is different from the virtual node of a component. If the tag is a component, a component vnode should be rendered.

export function isReservedTag(str) {
 let reservedTag = "a,div,span,p,img,button,ul,li";
 return reservedTag.includes(str);
}

1. Create component virtual nodes

createComponent creates a virtual node of a component, and distinguishes whether it is a component by whether there is a hook on the data

export function createElement(vm, tag, data = {}, ...children) {
  // If tag is a component, it should render a component's vnode
  if (isReservedTag(tag)) {
    return vnode(vm, tag, data, data.key, children, undefined);
  } else {
    const Ctor = vm.$options.components[tag]
    return createComponent(vm, tag, data, data.key, children, Ctor);
  }
}
// Create a virtual node for the component, in order to distinguish between components and elements data.hook 
function createComponent(vm, tag, data, key, children, Ctor) {
  // Component constructor if (isObject (Ctor)) {
    Ctor = vm.$options._base.extend(Ctor); // Vue.extend 
  }
  data.hook = { // This initialization method needs to be called when rendering the component init(vnode){
      let vm = vnode.componentInstance = new Ctor({_isComponent:true}); // new Sub will use this option and component configuration to merge vm.$mount(); // After the component is mounted, it will be in vnode.componentInstance.$el 
    }
  }
  return vnode(vm,`vue-component-${tag}`,data,key,undefined,undefined,{Ctor,children})
}

2. Create the actual node of the component

typeof tag === "string", it may be a virtual node of a component, then createComponent is called.

export function patch(oldVnode,vnode){
  // 1. Determine whether to update or render if(!oldVnode){
    return createElm(vnode);
  }else{
    // ...
  }
}

function createElm(vnode) {
 let { tag, data, children, text, vm } = vnode;
 if (typeof tag === "string") {
  if (createComponent(vnode)) {
   //Return the real node corresponding to the component return vnode.componentInstance.$el;
  }
  vnode.el = document.createElement(tag); // The virtual node will have an el attribute corresponding to the real node children.forEach((child) => {
   vnode.el.appendChild(createElm(child));
  });
 } else {
  vnode.el = document.createTextNode(text);
 }
 return vnode.el;
}

createComponent determines whether the component is a virtual node by whether there is a hook.init method on the data

If yes, call data.hook.init on the component

Create a component instance and assign it to vnode.componentInstance

If vnode.componentInstance has a value, it means the real DOM of the corresponding component has been generated.

function createComponent(vnode) {
  let i = vnode.data;
  if((i = i.hook) && (i = i.init)){
    i(vnode);
  }
  if(vnode.componentInstance){
    return true;
  }
}

Call the init method to create an instance of the component and mount it

data.hook = {
  init(vnode){
    let child = vnode.componentInstance = new Ctor({});
    child.$mount(); // Component mounting}
}

summary

New component (). $mount () => vm. $el

Insert the component's $el into the parent container (parent component)

It's done!

The above is how Vue components are parsed and rendered? For more details about vue component parsing and rendering, please pay attention to other related articles on 123WORDPRESS.COM!

You may also be interested in:
  • In-depth understanding of Vue dynamic components and asynchronous components
  • Steps for Vue to use Ref to get components across levels
  • Vue implements multi-tab component
  • Simple usage example of vue recursive component
  • Vue implements an Input component that gets the key display shortcut key effect
  • Example of communication between parent and child components of Vue (props, $ref, $emit)
  • Use of Vue mounted components
  • How does Vue reference other components (css and js)
  • Pop-up layer component of vue-dialog
  • Summary of Vue component basics

<<:  Vue implements an Input component that gets the key display shortcut key effect

>>:  Java example code to generate random characters

Recommend

CSS stacking and z-index example code

Cascading and Cascading Levels HTML elements are ...

Detailed explanation of dynamic Christmas tree through JavaScript

Table of contents 1. Animated Christmas Tree Made...

How to install JDK and Mysql on Ubuntu 18.04 Linux system

Platform deployment 1. Install JDK step1. Downloa...

About the pitfalls of implementing specified encoding in MySQL

Written in front Environment: MySQL 5.7+, MySQL d...

Share some key interview questions about MySQL index

Preface An index is a data structure that sorts o...

Detailed explanation of MySQL database (based on Ubuntu 14.0.4 LTS 64 bit)

1. Composition and related concepts of MySQL data...

Detailed explanation of JS browser event model

Table of contents What is an event A Simple Examp...

The button has a gray border that is ugly. How to remove it?

I used the dialog in closure and drew a dialog wit...

How to create Baidu dead link file

There are two types of dead link formats defined b...

Baidu Input Method opens API, claims it can be ported and used at will

The relevant person in charge of Baidu Input Metho...

Web page header optimization suggestions

Logo optimization: 1.The logo image should be as ...

Detailed explanation of sshd service and service management commands under Linux

sshd SSH is the abbreviation of Secure Shell, whi...

js native waterfall flow plug-in production

This article shares the specific code of the js n...

Sample code for separating the front-end and back-end using FastApi+Vue+LayUI

Table of contents Preface Project Design rear end...