Vue.$mount 发生了什么

首先附上$mount相关源码

// runtime-only 和 runtime-compiler版本中$mount方法都需要执行的部分
Vue.prototype.$mount = function ( el, hydrating ) { el = el && inBrowser ? query(el) : undefined; return mountComponent(this, el, hydrating) };

// 先缓存$mount方法,
var mount = Vue.prototype.$mount;
// runtime-compiler版本中,生成了render函数,并调用缓存的mount方法 Vue.prototype.$mount
= function ( el, hydrating ) { el = el && query(el); // 1、通过传入el获取dom元素 (query方法通过document.querySelector(el) 获取dom元素并返回) /* 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 } var options = this.$options; // resolve template/el and convert to render function if (!options.render) { // 2、render方法不存在时 var template = options.template; if (template) { // 3、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) { // 4、template不存在,el存在, 通过getOutHtml(el)获取模板赋值给template template = getOuterHTML(el); } if (template) { // 5、template赋值完成之后,转换为render函数,赋值给vm.$options /* istanbul ignore if */ if (process.env.NODE_ENV !== 'production' && config.performance && mark) { mark('compile'); } var ref = compileToFunctions(template, { outputSourceRange: process.env.NODE_ENV !== 'production', shouldDecodeNewlines: shouldDecodeNewlines, shouldDecodeNewlinesForHref: shouldDecodeNewlinesForHref, delimiters: options.delimiters, comments: options.comments }, this); var render = ref.render; var staticRenderFns = ref.staticRenderFns; options.render = render; options.staticRenderFns = staticRenderFns; /* istanbul ignore if */ if (process.env.NODE_ENV !== 'production' && config.performance && mark) { mark('compile end'); measure(("vue " + (this._name) + " compile"), 'compile', 'compile end'); } } } return mount.call(this, el, hydrating) // 6、最终调用mount方法 };

总结:当new Vue实例时,同时传入el、template、render函数时,后面的会覆盖前面的 (el为必传参数)

new Vue({
  el: '#app',
  template: `<p>{{ message }}</p>`,
  render(createElement) {
    return createElement('span', this.message)
  },
  data: {
    message: 'hello world'
  },
  mounted() {
    console.log(this.message)
  }
})
// 最终渲染在页面上的是span标签

 

render 函数如何生成后续再补充

posted @ 2020-09-24 22:47  爱吃橘子哇咔咔  阅读(320)  评论(0)    收藏  举报