运行机制概述
初始化及挂载
- 在 new Vue() 之后。 Vue 会调用 _init 函数进行初始化
- 初始化生命周期、事件、 props、 methods、 data、 computed 与 watch 等
- 通过 Object.defineProperty 设置 setter 与 getter 函数,用来实现
响应式
以及依赖收集
- 初始化之后调用 $mount 挂载组件
- 如果是运行时编译,即不存在 render function
- 存在 template 的情况,需要进行
编译
步骤。
编译
compile编译分为 ,
,三个阶段,最终需要得到parse
使用正则表达式等方式解析
Template模板中的指令,class,style等等数据,形成
optimize
optimize 的主要作用是,当 update
更新界面时,会有一个 patch
的过程, diff
算法会直接跳过静态节点,从而减少了比较的过程,优化了 patch
的性能
generate
generate 是将 AST
转化成 render function
字符串的过程,得到结果是 render 的字符串以及 字符串。
在经历过 parse
,optimize
,generate
这三个阶段以后,组件中就会存在渲染 所需的 render function
了
响应式
getter
跟 setter
在 init 的时候通过 Object.defineProperty 进行了绑定
- 当被设置的对象被读取的时候会执行
getter
函数 - 当被赋值的时候会执行
setter
函数
当 render function
被渲染的时候,因为会读取所需对象的值,所以会触发 getter
函数进行依赖收集,目的是将观察者 Watcher
对象存放到当前闭包中的订阅者 Dep
的 subs
中
修改对象的值的时候,会触发对应的 setter
, setter
通知之前依赖收集得到的 Dep
中的每一个 Watcher
,告知他们我的值改变了,需要重新渲染视图。这时候这些 Watcher
就会开始调用 update
来更新视图,当然这中间还有一个 patch
的过程以及使用队列来异步更新的策略
Virtual DOM
render function
会被转化成 VNode
节点
Virtual DOM
是一棵以 JavaScript 对象( VNode 节点)作为基础的树,用对象属性来描述节点,实际上它只是一层对真实 DOM 的抽象- 最终可以通过一系列操作使这棵树映射到真实环境上
- Virtual DOM 是以 JavaScript 对象为基础而不依赖真实平台环境,所以它具有了跨平台的能力
- 浏览器平台
- Weex
- Node
- ...
简单示例
{
tag: 'div',
children: [
{
tag: 'a',
text: 'click me'
}
]
}
{
tag: 'div',
children: [
{
tag: 'a',
text: 'click me'
}
]
}
渲染为
<div>
<a>click me</a>
</div>
<div>
<a>click me</a>
</div>
更新视图
在修改一个对象值的时候,会通过 setter
-> Watcher
-> update
的流程来修改对应的视图
当数据变化后,执行 render function
就可以得到一个新的 VNode
节点,将新 VNode
与旧 VNode
一起传入 patch
进行比较,经过 diff 算法得出它们的差异
,只需要将这些差异
的对应 DOM 进行修改即可。