Vue详解

本篇文章,我尝试这用自己的理解,结合着Vue源码,回答一个what is Vue?的问题。

声明: 本篇文章基于Vue源码版本2.6.8

Vue是一个类

从最开始开始

我们从Vue教程的第一个示例开始:

1
2
3
4
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
{{ message }}
</div>

1
2
3
4
5
6
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
}
})

引入Vue.js文件后,我们就可以直接全局使用Vue了。所以,Vue.js这个文件中肯定做了这么一件事:声明Vue函数。

所以,源码中肯定有这么一行:

1
function Vue() {}

另外,我们看到Vue使用了new命令调用,那么,它在源码中,一定被封装成了一个类方法。

Vue这个类

既然是类,那么它肯定有两样东西:静态属性和静态方法(在类上,会被子类继承)、原型方法和原型属性(在原型对象上,会被实例继承)。

我们分别来看一下,先看静态属性和静态方法:

1
2
3
4
5
6

Object.getOwnPropertyNames(Vue)

// ["length", "name", "prototype", "config", "util", "set", "delete", "nextTick", "observable", "options", "use", "mixin", "cid", "extend", "component", "directive", "filter", "FunctionalRenderContext", "version", "compile"]

// ["config", "util", "options", "cid", "FunctionalRenderContext", "version"]

一个有20个静态属性和静态方法。我们先给这20个属性/方法分个类。

第一类:函数自带的属性,即是个函数都会有的属性。包括lengthnameprototype

第二类:出现在Vue官方API文档-全局API章节中的,这些是暴露给用户使用的。包括extendnextTicksetdeletedirectivefiltercomponentusemixincompileobservableversion

第三类:未在文档中出现的,即只在源码内部使用,不推荐给用户使用的。包括cidoptionsconfigutilFunctionalRenderContext

我们(按照从简单到复杂)逐个看下:

name

默认参数,就是函数名

prototype

指向类的实例对象。

length

函数形参的个数

1
Vue.length // 1

形参个数是1,说明实例化Vue的时候,最多传一个参数就够了,多传了也没用。

version

Vue当前的版本号。

version在源码src/core/index.js#L24中被定义。

1
Vue.version = '__VERSION__'

而它具体的取值,会在Vue项目打包时确定,在Vue打包的配置文件中我们可以看到如下代码:

1
2
3
4
5
6
7
8
const version = process.env.VERSION || require('../package.json').version

...

const vars = {
__VERSION__: version
}
...

version的值会优先使用打包命令传来的值,如果没传,就使用package.json文件version字段的值。

至于version的用途,API文档中已经说得很明白:提供字符串形式的 Vue 安装版本号。这对社区的插件和组件来说非常有用,你可以根据不同的版本号采取不同的策略

cid

Vue类及其子类的唯一标识。

cid源码/src/core/global-api/extend.js#L13被定义。
值为0。

1
2
3
4
5
6
7
8
9
10
11
12
13
Vue.cid = 0
let cid = 1
Vue.extend = function () {
...
// 子类的constructor方法
const Sub = function VueComponent (options) {
this._init(options)
}
...
Sub.cid = cid++
...
return Sub
}

另外,我们也看到,在内存中也声明了一个cid变量,默认值为1。Vue.extend是创建Vue子类的方法。所以,以后每个使用Vue.extend方法创建的子类也会有个默认的cid属性,并且从1开始逐渐递增。

config

这个属性可以在API文档中找到,它是一个对象,包含 Vue 的全局配置。文档中列出了可以修改的一些属性。但其实这个对象上的属性和方法远不止这些。

1
2
3
Object.getOwnPropertyNames(Vue.config)

// ["optionMergeStrategies", "silent", "productionTip", "devtools", "performance", "errorHandler", "warnHandler", "ignoredElements", "keyCodes", "isReservedTag", "isReservedAttr", "isUnknownElement", "getTagNamespace", "parsePlatformTagName", "mustUseProp", "async", "_lifecycleHooks"]

我们逐个看: