全手打原创,转载请标明出处:https://www.cnblogs.com/dreamsqin/p/14945934.html, 多谢,=。=~(如果对你有帮助的话请帮我点个赞啦)
作为一个Web前端开发人员,使用Vue框架进行项目开发已经有一阵子,掐指一算,是时候认真探索一下Vue的底层了,以前的了解比较偏理论,这一次打算在弄清基本原理的前提下自己手写Vue中的核心部分,也许这样我才敢说自己“深入理解”了Vue,话不多说,开干,先聊聊大家熟知的理论部分~
Vue工作机制
初始化
-
在执行
new Vue()
之后,会创建一个Vue实例并进行初始化操作,包括生命周期(beforeCreate
、created
、beforeMount
、mounted
、beforeUpdate
、updated
、beforeDestroy
、destroyed
)、事件、props、methods、data、computed、watch等。 -
其中最重要的就是通过
Object.defineProperty
重写data
对象中各个属性的setter
及getter
方法,用于实现【响应式】和【依赖收集】。 -
初始化完成后会调用
$mount
将Vue实例挂载到指定的dom
节点。
工作流程
基于Vue源码整理出了一张总览图,我们可以清晰的看到Vue的整个工作机制:
-
init
即初始化,上面已经对初始化做了简单概述。 -
compile
即编译器,主要是对template
模板(Vue中的html代码)进行扫描,最终生成一些渲染函数,同时实现依赖收集(作用是当数据更新时我们可以知道去界面中更新哪个DOM节点)。 -
render function
即渲染函数,用于生成虚拟DOM树。我们在做数据更新时,修改的数据并不是进行真实的DOM操作,而是虚拟DOM上的数值,在做更新之前还会进行diff算法
比较,根据最新值和旧值计算出需要做的最小更新。 -
Watcher
即观察者,数据发生变化时实现感知,调用更新函数,从而进行补丁操作。 -
patch
即补丁操作,根据数据变化实现界面更新。目的是通过JS的计算时间换取DOM操作时间,从而提高性能。核心思想是减少页面渲染的次数及数量。
Vue响应式原理
为了方便后续手撸MVVM,在上述工作流程的基础上实现了简化:
编译
-
parse
:使用正则解析template
中的Vue指令(v-xxx)变量等等,最终形成语法树AST
。 -
optimize
:标记一些静态节点,用作后面的性能优化,在做diff算法
的时候直接略过。 -
generate
:把第一部分生成的AST
(抽象语法树:Abstract Syntax Tree)转化为渲染函数render function
。
响应式
初始化时通过Object.defineProperty
进行绑定,设置通知机制。当编译器生成的渲染函数被实际渲染时,会触发getter
进行依赖收集,在数据变化时触发setter
进行更新。
虚拟DOM
Virtual DOM
是React首创,Vue2开始支持,就是用JavaScript对象来描述DOM结构,数据修改时,我们先修改虚拟DOM中的数据,然后对数据进行diff算法
计算,最后汇总所有的diff
,力求做最少的DOM操作,毕竟在js里面对比很快,而真实的DOM操作太慢。
// VDOM
{
"tag": "div",
"props": {
"name": "dreamsyang",
"style": {
"color": "red"
},
"onClick": xxx
},
"children": [
{
"tag": "a",
"text": "click me"
}
]
}
<div name="dreamsyang" style="color: red;" @click="xxx">
<a>
click me
</a>
</div>
参考资料
1、Vue官方文档:https://cn.vuejs.org/;
2、Vue源码:https://github.com/vuejs/vue;