How Vue Transforms a .vue Component into a VNode
This article explains step by step how Vue.js converts a .vue component file into a virtual DOM node by using Vue.extend, createComponent, installComponentHooks, and the VNode constructor, illustrated with real source code snippets and detailed commentary.
In the previous article we covered Vue's virtual DOM and how vm._render turns JavaScript‑generated DOM data into a vnode; this piece focuses on the core concept of componentization, where a page is split into reusable .vue files that form a component tree.
To illustrate the component creation process, a simple demo is shown:
import Vue from 'vue'
import app from '@app'
Vue.config.productionTip = false
console.log(app)
new Vue({
el: '#root',
render: h => {
const vnode = h(app)
console.log(vnode)
return vnode
}
})
// app.vueRunning this demo shows that the app component is processed by Vue plugins into an object, which is later passed to the internal _createElement function defined in src/core/vdom/create-element.js . The function distinguishes between ordinary HTML tags and component tags, delegating the latter to createComponent .
export function createElement (context, tag, data, children, normalizationType, alwaysNormalize) {
// ...
if (typeof tag === 'string') {
// ordinary HTML vnode (covered previously)
} else {
// component case
vnode = createComponent(tag, data, context, children)
}
// ...
}
export function createComponent (Ctor, data, context, children, tag) {
if (isUndef(Ctor)) return
const baseCtor = context.$options._base
if (isObject(Ctor)) {
Ctor = baseCtor.extend(Ctor)
}
// ... validation, async handling, etc.
installComponentHooks(data)
const name = Ctor.options.name || tag
const vnode = new VNode(
`vue-component-${Ctor.cid}${name ? `-${name}` : ''}`,
data, undefined, undefined, undefined, context,
{ Ctor, propsData, listeners, tag, children },
asyncFactory
)
return vnode
}The baseCtor is the Vue constructor itself ( Vue.options._base ), set during the global API initialization. When Ctor is an object, Vue calls baseCtor.extend(Ctor) , which creates a subclass constructor with its own options , cid , and prototype chain.
Vue.extend = function (extendOptions) {
const Super = this
const SuperId = Super.cid
const cachedCtors = extendOptions._Ctor || (extendOptions._Ctor = {})
if (cachedCtors[SuperId]) return cachedCtors[SuperId]
const name = extendOptions.name || Super.options.name
const Sub = function VueComponent (options) { this._init(options) }
Sub.prototype = Object.create(Super.prototype)
Sub.prototype.constructor = Sub
Sub.cid = cid++
Sub.options = mergeOptions(Super.options, extendOptions)
Sub.super = Super
// copy static assets, register self‑component, etc.
cachedCtors[SuperId] = Sub
return Sub
}After the constructor is prepared, installComponentHooks merges Vue's built‑in component lifecycle hooks ( init , prepatch , insert , destroy ) into the vnode's data.hook object, ensuring that component‑specific behavior runs during the patch process.
function installComponentHooks (data) {
const hooks = data.hook || (data.hook = {})
for (let i = 0; i < hooksToMerge.length; i++) {
const key = hooksToMerge[i]
const existing = hooks[key]
const toMerge = componentVNodeHooks[key]
if (existing !== toMerge && !(existing && existing._merged)) {
hooks[key] = existing ? mergeHook(toMerge, existing) : toMerge
}
}
}
const componentVNodeHooks = {
init (vnode, hydrating) { /* ... */ },
prepatch (oldVnode, vnode) { /* ... */ },
insert (vnode) { /* ... */ },
destroy (vnode) { /* ... */ }
}
const hooksToMerge = Object.keys(componentVNodeHooks)Finally, a new VNode instance is created with a tag like vue-component-1-MyComponent , the prepared data, and a componentOptions object that stores the constructor, props, listeners, and children. This vnode is later passed to vm._update for rendering into real DOM.
In summary, Vue creates a component vnode by (1) extending the base Vue constructor to obtain a component subclass, (2) initializing component options and installing lifecycle hooks, and (3) constructing a VNode that represents the component in the virtual DOM.
Xueersi Online School Tech Team
The Xueersi Online School Tech Team, dedicated to innovating and promoting internet education technology.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.