PrefaceThis article will explain how Vue components are parsed and rendered.
<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 principleIn 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 methodVue.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 methodThe 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 mergingMerge 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 mergeMerge 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 principleWhen 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 nodescreateComponent 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 componenttypeof 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} } summaryNew 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:
|
<<: Vue implements an Input component that gets the key display shortcut key effect
>>: Java example code to generate random characters
Recently, the company is preparing to develop an ...
Basic Introduction Features Flexbox is a CSS disp...
Preface: I encountered a requirement to extract s...
Problem Description When we are working on a proj...
Table of contents 1. Write Webshell into outfile ...
Table of contents Overview Application scenarios ...
Preface This article mainly shares with you the g...
CSS Styles html,body{ width: 100%; height: 100%; ...
Large Text Data Types in Oracle Clob long text ty...
Preface In the development of small programs, we ...
Save the following code as the default homepage fi...
Table of contents The difference between hash and...
Table of contents background accomplish 1. Encaps...
View the IP address of the Container docker inspe...
Table of contents 1. Background of WAF 2. What is...