$mount function execution location

The _init private method is bound to the Vue prototype when initMixin is executed.

How to mount a component to a specified element

The $mount function defines the position

The $mount function defines two positions:

The first is in the SRC/platforms/web/runtime/index. Js

$mount is a public mount method. This is because there are many builds of Vue, some of which rely on this method for some customization, which will be explained later.

// Public mount method // el: can be a string or Dom element // Hydrating is the Virtual Dom patch algorithm parameter vue.prototype.$mount = function( el? : string | Element, hydrating? : Boolean): Component {// determine the EL, as well as the host environment, and then override the EL using the query utility function. el = el &&inBrowser ? Query (el) : undefined // Performs the actual mount and returnsreturn mountComponent(this, el, hydrating)
}
Copy the code

SRC/platforms/web/runtime/index. The js file is the runtime version of the entrance to the Vue file, so this method is a runtime version Vue $mount of execution.

For details about the different builds of Vue, see Vue’s explanation of the different builds.

You can also learn about the query function encapsulated by the author:

/**
 * Query an element selector if it's not an element already. */ export function query (el: string | Element): Element { if (typeof el === 'string') { const selected = document.querySelector(el) if (! Process.env.node_env! = = 'production' && warn( 'Cannot find element: Return document.createElement(' + el) // Error tolerance if not founddiv') } return selected } else { return el } }Copy the code

The second place to define the $mount function is in the SRC /platforms/web/entry-runtime-with-compiler.js file, which is the entry file for the full Vue(runtime + compiler).

Runtime + Compiler vs. Compiler Only the runtime is included.

// Cache run-time defined public$mountConst mount = vue.prototype.$mount
Vue.prototype.$mount = function( el? : string | Element, hydrating? : Boolean): Component {// Override EL (mount point: Component mount) el = el && query(el) /* Istanbul ignoreif* / / / tip can't put the body/HTML as a mount point, the development environment is given error / / because the mount point will be replaced by component template itself, obviously the body/HTML can not be replacedif(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
  }
  // $optionsNew Vue(options) is executed inside the _init method$optionsYou can access all properties of options such as data, Filter, Components, and directives const options = this.$options
  // resolve template/el and convert to render function// If the render function is included, the execution jumps out and directly executes the runtime version$mountmethodsif(! Options. Render) {// The template property is preferred when there is no render functionlet template = options.template
    if(template) {// Template exists and the type of template is stringif (typeof template === 'string') {
        if (template.charAt(0) === The '#') {// template is ID template = idToTemplate(template) /* Istanbul ignoreif* /if(process.env.NODE_ENV ! = ='production' && !template) {
            warn(
              `Template element not found or is empty: ${options.template}`,
              this
            )
          }
        }
      } else if(template.nodetype) {// If the template type is an element node, use the innerHTML of that element as the template template = template.innerHTML}else{// If template is neither a string nor an element node, the development environment will prompt the developer that the template option passed is invalidif(process.env.NODE_ENV ! = ='production') {
          warn('invalid template option:' + template, this)
        }
        return this
      }
    } else if(el) {// If the template option does not exist, then use the outerHTML of the EL element as the template content. Template = getOuterHTML(el)if (template) {
      /* istanbul ignore if* /if(process.env.NODE_ENV ! = ='production' && config.performance && mark) {
        mark('compile'} // Get the converted render function with staticRenderFns and hang on$optionsConst {render, staticRenderFns} = compileToFunctions(template, {outputSourceRange: process.env.node_env! = ='production',
        shouldDecodeNewlines,
        shouldDecodeNewlinesForHref,
        delimiters: options.delimiters,
        comments: options.comments
      }, this)
      options.render = render
      options.staticRenderFns = staticRenderFns

      /* istanbul ignore if*/ // use this to measure compiler performance. Config is a global configuration objectif(process.env.NODE_ENV ! = ='production' && config.performance && mark) {
        mark('compile end')
        measure(`vue ${this._name} compile`, 'compile'.'compile end'}}} // call the public mount method // override$mountMethod is used to add functionality for template compilationreturn mount.call(this, el, hydrating)
}
Copy the code

About the idToTemplate method: Get the ID from the QUERY to get the DOM and use the innerHTML of the element as the template

const idToTemplate = cached(id => {
  const el = query(id)
  return el && el.innerHTML
})

Copy the code

GetOuterHTML method:

/**
 * Get outerHTML of elements, taking care
 * of SVG elements in IE as well.
 */
function getOuterHTML (el: Element): string {
  if (el.outerHTML) {
    return el.outerHTML
  } elseConst Container = document.createElement() const container = document.createElement() const Container = document.createElement();'div')
    container.appendChild(el.cloneNode(true))
    return container.innerHTML
  }
}
Copy the code

For compileToFunctions, see SRC /platforms/web/entry- Runtime -with-compiler.js that will be mounted to Vue as a global method.

The mountComponent method: actually executes the bound component

MountComponent function is in the SRC/core/instance/lifecycle. Js.

export functionMountComponent (VM: Component, // vm EL:? Element, // mount point hydrating? : Boolean): Component {// Add to the Component instance object$elAttributes / /$elThe value of is the reference VM for the root element of the component template.$el = el
  if(! vm.$options.render) {// The render function does not exist, an empty VNode object VM will be created.$options.render = createEmptyVNode
    if(process.env.NODE_ENV ! = ='production') {
      /* istanbul ignore if* /if ((vm.$options.template && vm.$options.template.charAt(0) ! = =The '#') ||
        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.'}}} // Triggers beforeMount lifecycle hook callHook(VM,'beforeMount'// the function vm._render calls the VM.$optionsRender function and return the generated virtual node (vnode) Template => render => vnode // v._update (); vnode => real dom nodeletUpdateComponent // Renders the virtual DOM generated by the render function to a real DOM /* Istanbul ignoreif* /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// Create an observer of the Render function, which relies heavily on the vm._watcher being already defined. New watcher (vm, updateComponent, noop, {before () {if (vm._ismounted &&! vm._isDestroyed) { 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