Source analysis of MOUNT

In Vue we use the mount instance method to mount the VM, the mount instance method to mount the VM, the mount method is defined in multiple files, Such as the SRC/platform/web/entry – the runtime – with – compiler. Js, SRC/platform/web/runtime/index js, SRC/platform/weex/runtime/index. Js. The implementation of mount depends on the platform and how it is built. Next, we will focus on the implementation of mount with the compiler version, which is related to the platform and the construction method. Next, we will focus on the implementation of mount with the compiler version, which is related to the platform and the construction method. Next, we’ll focus on the Implementation of Monut with the Compiler version, because we’ll get a better understanding of how VUE works in a purely front-end browser environment, rather than webPack’s Vue-Loader.

SRC /platform/web/ entry-Runtime-with-compiler. js

const mount = Vue.prototype.$mount Vue.prototype.$mount = function ( el? : string | Element, hydrating? : boolean ): Component { el = el && query(el) /* istanbul ignore if */ if (el === document.body || el === document.documentElement) {  process.env.NODE_ENV ! == 'production' && warn( `Do not mount Vue to <html> or <body> - mount to normal elements instead.` ) return this } const options = this.$options // resolve template/el and convert to render function if (! options.render) { let template = options.template if (template) { if (typeof template === 'string') { if (template.charAt(0) === '#') { template = idToTemplate(template) /* istanbul ignore if */ if (process.env.NODE_ENV ! == 'production' && ! template) { warn( `Template element not found or is empty: ${options.template}`, this ) } } } else if (template.nodeType) { template = template.innerHTML } else { if (process.env.NODE_ENV ! == 'production') { warn('invalid template option:' + template, this) } return this } } else if (el) { template = getOuterHTML(el) } if (template) { /* istanbul ignore if */ if (process.env.NODE_ENV ! == 'production' && config.performance && mark) { mark('compile') }Copy the code

I drew a rough flow chart to show it clearly

Graph TD cache $mount --> Vue cannot be mounted to body\ HTML --> undefined render --> create render method --> finally call compileToFunctions to implement compilation

Let’s examine the code that first caches the mount method on the prototype and then redefines that method. First of all, it restricts EL. Vue cannot be mounted on root nodes such as body and HTML. Next comes the crucial logic — if no render method is defined, the el or template string is converted to the Render method. It is important to remember that in Vue2.0, all Vue components will eventually require the Render method, whether we develop the component in a single file, Vue, or write el or Template properties, which will eventually be converted to the Render method. So this is Vue’s “compile online” process, which is implemented by calling compileToFunctions, which we’ll cover later. Finally, let’s examine this code by calling the mount method on the original prototype and then redefining the method. First of all, it restricts EL. Vue cannot be mounted on root nodes such as body and HTML. Next comes the crucial logic — if no render method is defined, the el or template string is converted to the Render method. It is important to keep in mind that in Vue 2.0, all Vue components will eventually require the render method, whether we develop the component in a single file. Vue, or write el or Template properties, which will eventually be converted to the Render method. So this is Vue’s “compile online” process, which is implemented by calling compileToFunctions, which we’ll cover later. Finally, let’s examine this code by calling the mount method on the original prototype and then redefining the method. First of all, it restricts EL. Vue cannot be mounted on root nodes such as body and HTML. Next comes the crucial logic — if no render method is defined, the el or template string is converted to the Render method. It is important to remember that in Vue2.0, all Vue components will eventually require the Render method, whether we develop the component in a single file, Vue, or write el or Template properties, which will eventually be converted to the Render method. So this is Vue’s “compile online” process, which is implemented by calling compileToFunctions, which we’ll cover later. Finally, the mount method on the original prototype is called.

$mount on the original prototype method in SRC/platform/web/runtime/index defined in js, so the design is completely in order to reuse, because it can be used by the runtime only version of the Vue directly.

// public mount method Vue.prototype.$mount = function ( el? : string | Element, hydrating? : boolean ): Component { el = el && inBrowser ? query(el) : undefined return mountComponent(this, el, hydrating) }Copy the code

The $mount method supports passing two arguments. The first is el, which represents the element to be mounted, either a string or a DOM object. If it is a string, the browser will call the query method to convert it into a DOM object. The second parameter is related to server rendering, and we don’t need to pass the second parameter in the browser environment.

MountComponent method

$will actually go to the mount method call mountComponent method, this method defined in SRC/core/instance/lifecycle. The js file:

export function mountComponent ( vm: Component, el: ? Element, hydrating? : boolean ): Component { vm.$el = el if (! vm.$options.render) { vm.$options.render = createEmptyVNode if (process.env.NODE_ENV ! == 'production') { /* istanbul ignore if */ if ((vm.$options.template && vm.$options.template.charAt(0) ! == '#') || vm.$options.el || el) { warn( 'You are using the runtime-only build of Vue where the template ' + 'compiler is not available. Either pre-compile the templates into ' + 'render functions, or use the compiler-included build.', vm ) } else { warn( 'Failed to mount component: template or render function not defined.', vm ) } } } callHook(vm, 'beforeMount') let updateComponent /* istanbul ignore if */ if (process.env.NODE_ENV ! == 'production' && config.performance && mark) { updateComponent = () => { const name = vm._name const id = vm._uid const startTag = `vue-perf-start:${id}` const endTag = `vue-perf-end:${id}` mark(startTag) const vnode = vm._render() mark(endTag) measure(`vue ${name} render`, startTag, endTag) mark(startTag) vm._update(vnode, hydrating) mark(endTag) measure(`vue ${name} patch`, startTag, endTag) } } else { updateComponent = () => { vm._update(vm._render(), hydrating) } } // we set this to vm._watcher inside the watcher's constructor // since the watcher's initial patch may call $forceUpdate (e.g. inside child // component's mounted hook), which relies on vm._watcher being already defined new Watcher(vm, updateComponent, noop, { before () { if (vm._isMounted) { callHook(vm, 'beforeUpdate') } } }, true /* isRenderWatcher */) hydrating = false // manually mounted instance, call mounted on self // mounted is called for render-created child components in its inserted hook if (vm.$vnode == null) { vm._isMounted = true callHook(vm, 'mounted') } return vm }Copy the code

As you can see from the above code, the core of the mountComponent is to call the vm._render method to become a virtual Node and then instantiate a render Watcher, which calls the updateComponent method in its callback function. The final call to vm._update updates the DOM.

Watcher plays two roles here, one is to execute the callback function when initialization is performed and the other is to execute the callback function when the monitored data in the VM instance changes, which we will discuss in a later section.

_isMounted specifies that the instance is mounted and executes the mounted hook function. Note here that vm.$vnode represents the parent virtual Node of the Vue instance, so Null means the current instance of root Vue.