本篇文章进行来学习Angular框架,带大家了解一下Ivy编译器中的增量DOM,希望对大家有所帮助!
作为“为大型前端项目”而设计的前端框架,Angular 其实有许多值得参考和学习的设计,本系列主要用于研究这些设计和功能的实现原理。本文围绕 Angular 的核心功能 Ivy 编译器,介绍其中的增量 DOM 设计。【相关教程推荐:《angular教程》】
在介绍前端框架的时候,我常常会介绍到模板引擎。对于模板引擎的渲染过程,像 Vue/React 这样的框架里,使用了虚拟 DOM 这样的设计。
在 Angular Ivy 编译器中,并没有使用虚拟 DOM,而且使用了增量 DOM。
增量 DOM
在 Ivy 编译器里,模板编译后的产物与 View Engine 不一样了,这是为了支持单独编译、增量编译等能力。
比如,<span>My name is {{name}}</span>
这句模板代码,在 Ivy 编译器中编译后的代码大概长这个样子:
// create mode if (rf & RenderFlags.Create) { elementStart(0, "span"); text(1); elementEnd(); } // update mode if (rf & RenderFlags.Update) { textBinding(1, interpolation1("My name is", ctx.name)); }
可以看到,相比于 View Engine 中的elementDef(0,null,null,1,'span',...),
,elementStart()
、elementEnd()
这些 API 显得更加清爽,它们使用的便是增量 DOM 的设计。
增量 DOM vs 虚拟 DOM
虚拟 DOM 想必大家都已经有所了解,它的核心计算过程包括:
-
用 JavaScript 对象模拟 DOM 树,得到一棵虚拟 DOM 树。
-
当页面数据变更时,生成新的虚拟 DOM 树,比较新旧两棵虚拟 DOM 树的差异。
-
把差异应用到真正的 DOM 树上。
虽然虚拟 DOM 解决了页面被频繁更新和渲染带来的性能问题,但传统虚拟 DOM 依然有以下性能瓶颈:
- 在单个组件内部依然需要遍历该组件的整个虚拟 DOM 树
- 在一些组件整个模版内只有少量动态节点的情况下,这些遍历都是性能的浪费
- 递归遍历和更新逻辑容易导致 UI 渲染被阻塞,用户体验下降
针对这些情况,React 和 Vue 等框架也有