阅读 剖析 Vue.js 内部运行机制,自己做点小笔记,方便自己可以随时翻看,大家喜欢这篇文章,也可以去点击看原作哦~
初始化及挂载
image.png看图可知,new Vue() 后,会调用 _init 函数来初始化,这个过程,包括生命周期、data、props、methods、事件、computed、watch等。其中,Object.defineProperty 设置 setter 、getter 函数,用来实现「响应式」以及「依赖收集」。
初始化后调用 $mount 挂载组件,如果是运行时编译,即不存在 render function但是存在 template 的情况,需要进行「编译」步骤。
编译
compile 编译可以分成 parse、optimize 与 generate 三个阶段,最终需要得到 render function
image.png
响应式
image.png当 render function 被渲染的时候,因为会读取所需对象的值,所以会触发 getter 函数进行「依赖收集」,「依赖收集」的目的是将观察者 Watcher 对象存放到当前闭包中的订阅者 Dep 的 subs 中。形成如下所示的这样一个关系
image.png
在修改对象的值的时候,会触发对应的 setter, setter 通知之前「依赖收集」得到的 Dep 中的每一个 Watcher,告诉它们自己的值改变了,需要重新渲染视图。这时候这些 Watcher 就会开始调用 update 来更新视图
Virtual DOM
render function 会被转化成 VNode 节点。Virtual DOM 其实就是一棵以 JavaScript 对象(VNode节点)作为基础的树,用对象属性来描述节点,实际上它是一层对真实 DOM的抽象。最终可以通过一系列操作使这棵树映射到真实环境上。由于 Virtual DOM 是以 JavaScript 对象为基础而不依赖真实平台环境,所以使它具有了跨平台的能力,比如说浏览器平台、Weex、Node 等。
比如说:
{
tag: 'div', /*说明这是一个div标签*/
children: [ /*存放该标签的子节点*/
{
tag: 'button', /*说明这是一个a标签*/
text: 'click me' /*标签的内容*/
}
]
}
渲染后:
<div>
<button>click me</button>
</div>
这只是一个简单的例子,实际上的节点有更多的属性来标志节点,比如 isStatic (代表是否为静态节点)、 isComment (代表是否为注释节点)等
更新视图
image.png前面说到,修改一个对象值的时候,通过 setter -> Watcher -> update 的过程来修改对应的视图,那么,最终如何更新到视图呢?
当数据变化时,执行 render function 可以得到一个新的 VNode 节点,如果想得到新的视图,简单的方法就是直接解析 VNode 节点,用 innerHTML 全部渲染到真实的 DOM 中。但是,如果只对其中一小部分进行修改,哪咋办?
那么,这时候就需要用的 「patch」了。会将新的 VNode 与旧的 VNode 一起传入 patch 进行比较,然后 diff 算法得到差异。最后将差异的地方进行渲染即可
讲到这里,我们在一起看看全部的流程图
image.png
网友评论