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

How to use uni-app to display buttons and search boxes in the top navigation bar

Recently, the company is preparing to develop an ...

Understand CSS3 FlexBox elastic layout in 10 minutes

Basic Introduction Features Flexbox is a CSS disp...

Mysql string interception and obtaining data in the specified string

Preface: I encountered a requirement to extract s...

Vue two-choice tab bar switching new approach

Problem Description When we are working on a proj...

Summary of various postures of MySQL privilege escalation

Table of contents 1. Write Webshell into outfile ...

How to implement the observer pattern in JavaScript

Table of contents Overview Application scenarios ...

Detailed explanation of the general steps for SQL statement optimization

Preface This article mainly shares with you the g...

Implementation of HTML sliding floating ball menu effect

CSS Styles html,body{ width: 100%; height: 100%; ...

How to store text and pictures in MySQL

Large Text Data Types in Oracle Clob long text ty...

WeChat applet implementation anchor positioning function example

Preface In the development of small programs, we ...

HTML page jump code

Save the following code as the default homepage fi...

Detailed explanation of Vue's hash jump principle

Table of contents The difference between hash and...

Practice of dynamically creating dialog according to file name in vue+el-element

Table of contents background accomplish 1. Encaps...

Docker dynamically exposes ports to containers

View the IP address of the Container docker inspe...

Analysis of the principle of Nginx using Lua module to implement WAF

Table of contents 1. Background of WAF 2. What is...