我们知道 src/platforms/web 是 Vue 编译的入口,主要进行分析运行时版本(不携带编译器) entry-runtime.js 和编译器版本(携带编译器) entry-runtime-with-compiler.js 接下来我们看下它们的代码。
运行时(entry-runtime.js)
import Vue from './runtime/index';export default Vue;
运行时版本的代码很精简,主要就是在 src/platforms/web/runtime/index.js 导入了 Vue 然后导出 Vue。
编译器(entry-runtime-with-compiler.js)
import config from 'core/config';import { warn, cached } from 'core/util/index';import { mark, measure } from 'core/util/perf';import Vue from './runtime/index';import { query } from './util/index';import { compileToFunctions } from './compiler/index';import { shouldDecodeNewlines, shouldDecodeNewlinesForHref } from './util/compat';const idToTemplate = cached((id) => {const el = query(id);return el && el.innerHTML;});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 functionif (!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');}const { 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 */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);};/*** Get outerHTML of elements, taking care* of SVG elements in IE as well.*/function getOuterHTML(el: Element): string {if (el.outerHTML) {return el.outerHTML;} else {const container = document.createElement('div');container.appendChild(el.cloneNode(true));return container.innerHTML;}}Vue.compile = compileToFunctions;export default Vue;
携带编译器版本的代码在运行时的基础上,额外多出来了 90 多行的代码(仅限本文件)。主要的作用就是将 el 转换为 template 字符串,然后再将 template 转换为 render 函数。这里只作为简单介绍,后面将会深入介绍。
