在 new Vue()
之后。 Vue 会调用 _init
函数进行初始化,也就是这里的 init
过程,它会初始化生命周期、事件、 props、 methods、 data、 computed 与 watch 等。其中最重要的是通过 Object.defineProperty
设置 setter
与 getter
函数,用来实现「响应式」以及「依赖收集」,后面会详细讲到,这里只要有一个印象即可。
初始化之后调用 $mount
会挂载组件,如果是运行时编译,即不存在 render function 但是存在 template 的情况,需要进行「编译」步骤。
编译
compile编译可以分成 parse
、optimize
与 generate
三个阶段,最终需要得到 render function。
parse
parse
会用正则等方式解析 template 模板中的指令、class、style等数据,形成AST。
optimize
optimize
的主要作用是标记 static 静态节点,这是 Vue 在编译过程中的一处优化,后面当 update
更新界面时,会有一个 patch
的过程, diff 算法会直接跳过静态节点,从而减少了比较的过程,优化了 patch
的性能。
generate
generate
是将 AST 转化成 render function 字符串的过程,得到结果是 render 的字符串以及 staticRenderFns 字符串。
在经历过 parse
、optimize
与 generate
这三个阶段以后,组件中就会存在渲染 VNode 所需的 render function 了。
响应式
接下来也就是 Vue.js 响应式核心部分。
这里的 getter
跟 setter
已经在之前介绍过了,在 init
的时候通过 Object.defineProperty
进行了绑定,它使得当被设置的对象被读取的时候会执行 getter
函数,而在当被赋值的时候会执行 setter
函数。
当 render function 被渲染的时候,因为会读取所需对象的值,所以会触发 getter
函数进行「依赖收集」,「依赖收集」的目的是将观察者 Watcher 对象存放到当前闭包中的订阅者 Dep 的 subs 中。形成如下所示的这样一个关系。
在修改对象的值的时候,会触发对应的 setter
, setter
通知之前「依赖收集」得到的 Dep 中的每一个 Watcher,告诉它们自己的值改变了,需要重新渲染视图。这时候这些 Watcher 就会开始调用 update
来更新视图,当然这中间还有一个 patch
的过程以及使用队列来异步更新的策略