vue 源码:整体概况

180 阅读3分钟

初衷

也许你日常中经常使用到 new Vue() 来实例化一个 Vue 对象,但你却不知道它到底做了什么操作。你想知道,于是你打开 Vue 的源码,但被庞大的代码吓跑了。你不是一个人,我也一样。

来来去去我也打开过很多次 Vue 的源码,到现在依旧会有点抵抗。但我觉得还是需要先把我理解的先记录下来,日后再逐步完善。

Vue 的源码文章在网上有很多,我也阅读了不少。而我接下来记录的文章也是茫茫大海中的一滴水。不求比其他文章更加优秀,只希望能够给和我一样的你一丝丝帮助。

接下来看看 new Vue() 的一个大体流程吧。

大体流程

再多的文字解释也没有一张清晰的流程图更加容易理解。是时候祭出 @zhouweicsu 的这一张清晰又易理解的流程图。

在还没有打开 Vue 的源码之前,我们只需要有个大概的印象即可。可以将 Vue 分成两个过程,分别是 DOM 初始化DOM update

vue 2.0 模板渲染过程

DOM 初始化

在调用 new Vue() 后,例如以下代码:

<div id="app">
  {{ message }}
</div>
new Vue({
    el: '#app',
    data: {
        message: 'Hello Vue!'
    }
});

Vue 一方面会初始化状态(state),使用 Object.defineProperty 设置 data 等,此步骤在以上的流程图并没有画出来。

另一方面,Vue 会取得 HTML 模板,进行特殊的 compile() 操作,这一步比较复杂(暂时不展开),主要是将 HTML 模板中的 data 替换成真正要显示的数据,比如以上的例子会被替换成:

<div id="app">
  Hello Vue!
</div>

当然 compile() 操作远远不止这一些,像 v-if、v-for、动画都是在这里实现的。

最后会形成一个能够显示的 HTML 代码,Vue 并没有直接进行 innerHTML 操作,而是使用 render function 将 HTML 转成了虚拟 DOM,最后再一次性转成真实的 DOM。

至此,DOM 的初始化完成了,页面加载完毕。需要注意的,DOM 初始化时 VNode 是直接转成真实的 DOM,并不需要经过 diff 算法打补丁(patch)。

DOM update

在 DOM 初始化时,data 已经通过 Object.defineProperty 设置了 setter,当数据更新时,Vue 会触发调用 update(),即用新的 data 生成另一个新的即将渲染的 HTML 模板。

该新的 HTML 模板也会对应的变成一个新的虚拟 DOM,通过 diff 算法与当前旧的虚拟 DOM 进行比较,以打补丁的方式更新真实的 DOM。

具体的 diff 算法会在后面独立出来讲解。

最后完成 DOM 的 update。

最后

以上是 Vue 的一个大体脉络,得益于这一张形象的流程图,想必大家能够知道 Vue 的一个大概整体流程。

接下来将进入 Vue 的源码,对流程图上的步骤进行深入了解。