初衷
也许你日常中经常使用到 new Vue()
来实例化一个 Vue 对象,但你却不知道它到底做了什么操作。你想知道,于是你打开 Vue 的源码,但被庞大的代码吓跑了。你不是一个人,我也一样。
来来去去我也打开过很多次 Vue 的源码,到现在依旧会有点抵抗。但我觉得还是需要先把我理解的先记录下来,日后再逐步完善。
Vue 的源码文章在网上有很多,我也阅读了不少。而我接下来记录的文章也是茫茫大海中的一滴水。不求比其他文章更加优秀,只希望能够给和我一样的你一丝丝帮助。
接下来看看 new Vue()
的一个大体流程吧。
大体流程
再多的文字解释也没有一张清晰的流程图更加容易理解。是时候祭出 @zhouweicsu 的这一张清晰又易理解的流程图。
在还没有打开 Vue 的源码之前,我们只需要有个大概的印象即可。可以将 Vue 分成两个过程,分别是 DOM 初始化
和 DOM update
。
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 的源码,对流程图上的步骤进行深入了解。