深入解读vue源码(三)runtime-compiler入口

基本介绍

上篇文章较为全面的介绍了整个vue源码在执行build过程中的构建过程,在文章的最后还介绍了两种不同的构建方式,分别是runtime onlyruntime compiler

值得注意的是这两种构建方式都是基于web环境参数下的构建方式,weex并不在这个范围内。

本篇文章我们会对runtime compiler这种构建方式的入口进行分析,之所以选择这种构建方式介绍是因为runtime compiler相对于runtime only来说多了个编译器的功能,在这篇文章中都会一并介绍。

简单来说vue就是一个方法类,在这个方法中挂载了一些vue自带的方法等。


程序入口解析

entry-runtime-with-compiler分析

entry-runtime-with-compiler文件是runtime compiler构建方式下的入口文件,该文件路径在src/platforms/web/下。

下面的代码是从entry-runtime-with-compiler中抽象出来的mount方法。这种能够表达代码结果和逻辑的代码我们称之为伪代码。伪代码并不能通过编译器的检查,更不能运行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const mount = Vue.prototype.$mount
Vue.prototype.$mount = function (el?: string | Element, hydrating?: boolean): Component {
......
const options = this.$options // new Vue(options)提供的实参options
if (!options.render) { // 使用实例化Vue时提供render函数,不是render函数的情况下进入
if (template) { // 如果没有提供render函数,则优先使用提供的template选项
......
} else if (el) { // 既没有提供render函数,又没有template选项,就使用el选项
template = getOuterHTML(el)
}
}
......
return mount.call(this, el, hydrating)
}

上面的这段伪代码用于将vue中的html模板编译成render函数,并且把$mount方法定义在vueprototype上,使得每一个new出来的vue实例都能使用此方法。

1
2
3
4
5
6
7
8
9
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
}
}

上面这段代码主要是得到html代码片段,它能够处理以下四种写法。

下面的这段代码,就是我们在使用vue时候在main.js最下面new的一个vue实例。

1
2
3
4
{el: '#index'}
{el: document.querySelector('#index')}
{template: '#index'}
{template: '<div>{{msg}}</div>'}

到这里基本讲解了下entry-runtime-with-compiler这个文件,我们通过引入的方式找到入口的核心。

1
2
3
4
// src/platforms/web/entry-runtime-with-compiler.js
import Vue from './runtime/index'
// src/platforms/web/runtime/index.js
import Vue from 'core/index'

在这个文件中还有一个compileToFunctions方法,这个方法是mount方法内调用,通过编译器将html转换为render函数的方法,在此就先不在赘述。

src/core/index分析

core/index.js是核心代码的入口。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import Vue from './instance/index'
import { initGlobalAPI } from './global-api/index' // 全局api
import { isServerRendering } from 'core/util/env' // 布尔类型变量,判断是否是ssr
......
initGlobalAPI(Vue) // 开始执行初始化全局变量
// 为vue原型定义$isServer方法
Object.defineProperty(Vue.prototype, '$isServer', {
get: isServerRendering
})
// 为vue原型定义$isServer方法
Object.defineProperty(Vue.prototype, '$ssrContext', {
get () {
/* istanbul ignore next */
return this.$vnode && this.$vnode.ssrContext
}
})
......
Vue.version = '__VERSION__'
export default Vue
src/core/instance/index分析

该文件定义了一个vue的类,然后又调用了一系列initmixin这样的方法来初始化一些功能,具体的在之后的文章中我们再进行深入的分析。


总结

这篇文章简单的介绍了下vue的入口,后续的文章会对每一部分进行详细的介绍。

------本文结束,感谢您的阅读,如有问题请通过邮件方式联系作者------