为什么学习 Vue ?
Vue简单:简单到后端同学看看就会了。Vue在每个维度之间,做了非常好的权衡和取舍,算是一个非常中庸且优雅的框架,兼顾响应式、虚拟DOM、运行时和编译优化。
其他框架特点:
-
React注重数据不可变、虚拟DOM和运行时 -
Svelte运行时都非常轻量级,侧重在于编译时的优化 -
Angular则在抽象这个维度又走向一个极致,生来就是为了复杂项目。
前端三大框架
AngularJS 的诞生,引领了前端 MVVM模式的潮流。
MVVM模式: (Model-View-ViewModel),在前端的场景下,把 Controller变成了 View-Model层,作为 Model和 View的桥梁,Model 数据层和 View 视图层交给 View-Model 来同步。
阶段一:利用数据驱动页面
面临核心问题:数据发生变化后,怎么去通知页面更新。
来看下三大框架各自是怎么处理的?
Angular 1解决方案:就是最老套的脏检查。
所谓的脏检查: 指的是 Angular 1 在对数据变化的检查上,遵循每次用户交互时都检查一次数据是否变化,有变化就去更新 DOM 这一方法。
这个方法看似简单粗暴,但算是数据驱动页面早期的实现,所以一经推出,就迅速占领了 MVVM 市场。
Vue 1 的解决方案:就是使用响应式。
- 初始化的时候,
Watcher监听了数据的每个属性。 - 数据发生变化的时候,就能精确地知道数据的哪个
key变了,去针对性修改对应的DOM即可。
React解决方案:通过虚拟 DOM ****计算出变化的数据,去进行精确的修改。
- 初始化的时候,在浏览器
DOM之上,搞了一个叫虚拟DOM的东西,也就是用一个JavaScript对象来描述整个DOM树。 - 这个对象就像数据和实际
DOM的一个缓存层,通过管理这个对象的变化,来减少对实际DOM的操作 - 数据变化后,只能通过新老数据的计算
Diff来得知数据的变化。
// 举个栗子:如下代码
<div id = "app">
<p class = "item">Item1</p>
<div class = "item">Item2</div>
</div>
// 对应 虚拟 DOM:
{
tag: "div",
attrs: {
id: "app"
},
children: [
{
tag: "p",
attrs: { className: "item" },
children: ["Item1"]
},
{
tag: "div",
attrs: { className: "item" },
children: ["Item2"]
}
]
}
浏览器操作 DOM 一直都是性能杀手,而虚拟 DOM 的 Diff 的逻辑,又能够确保尽可能少的操作 DOM,这也是虚拟 DOM 驱动的框架性能一直比较优秀的原因之一。
Vue2 解决:响应式数据过多,内存占用过多问题
这时的 React面临主要问题:虚拟DOM树 过大,影响性能。
React 为了突破性能瓶颈,借鉴了操作系统时间分片的概念,引入了 Fiber 架构。
就是把整个虚拟 DOM 树微观化,变成链表,
然后利用浏览器的空闲时间计算 Diff。一旦浏览器有需求,可以把没计算完的任务放在一旁,把主进程控制权还给浏览器,等待浏览器下次空闲。
树形结构的 Diff 很难中断;右侧是把树形结构改造成了链表,遍历严格地按照子元素 -> 兄弟元素 -> 父元素的逻辑,随时可以中断和恢复 Diff 的计算过程。
为了解决 Vue 1 的问题在于响应式数据过多,这样会带来内存占用过多的问题。
Vue 2 引入虚拟 DOM 来解决响应式数据过多的问题。
这个解决方案使用虚拟 DOM 解决了响应式数据过多的内存占用问题,又良好地规避了 React 中虚拟 DOM 的问题, 还通过虚拟 DOM 给 Vue 带来了跨端的能力。
- 响应式数据(推): 主动推送变化,组件之间变化。
- 虚拟DOM(拉): 被动计算数据的
Diff,组件内部的数据变化。
Vue3 在虚拟 DOM 的静态标记上做到了极致
Vue与 React区别:
React的世界里只有JSX,最终JSX都会在Compiler那一层。Vue的世界默认是template,也就是语法是限定死的。
Tips:``Svelte 这种框架,没有虚拟 DOM 的库,直接把模板编译成原生 DOM,几乎没有 Runtime,所有的逻辑都在 Compiler 层优化,算是另外一个极致。