第一篇
主要内容是介绍框架设计方面的知识,以及vue选择现在这些技术进行实现的原因
第一章 权衡的艺术
命令式和声名式
命令式和声名式是框架设计的两种范式。
其中,命令式注重过程,编写面向过程的代码,可以做到极致的性能优化(等于原生)。缺点是心智负担较大,且代码不易维护,特别是在大型的项目之中。
声名式则更注重代码结果,从具体的编写上来看就是html的树形结构和js操作dom的区别,声名式的编码更为直观,生产出来的代码也更易维护,缺点是性能可能较差。
性能与可维护性的权衡
结论:对web页面的编码,声名式的性能<=命令式的性能。
这里结合虚拟DOM进行解析。
我们在创建一个页面的时候:
- 可以通过直接操作DOM来得到页面,性能消耗为 innerHTML字符串+新建DOM元素
- 通过声名式来得到页面,性能消耗为 新建JS对象 + 新建所有DOM元素
这样来看,在新建页面的时候,命令式的操作一定会有更好的性能。
更新页面的时候:
- 每一个微小的更新都会导致所有的DOM节点的销毁和重建,消耗:重新渲染+新建
- 根据算法来找到需要更新的DOM节点进行更新,消耗:找到节点+更新对应节点
在不同的情况下,两种方法的效率不同。但在大部分情况下,使用声名式代码进行更新的效率会更高
虚拟DOM的性能
虚拟DOM的性能可以根据上面两种情况进行推断。这里进行权衡的指标主要是三个:心智负担、性能、可维护性
我们常用的三种渲染页面的方法:
- 直接使用innerHTML进行渲染。----心智负担适中、性能差、可维护性一般(在大型项目中)
- 使用虚拟DOM进行渲染。 ----心智负担小,性能可以接受,可维护性好
- 纯Js编码。 ----心智负担极大,性能理论最强,可维护性差。
所以,虚拟DOM是在各种权衡之间做出的选择。兼顾性能和可维护性。
编译时和运行时
编译时和运行时在web页面上来说,主要区别在于是否有中间转换的一个过程。
运行时(render函数),将用户代码进行转化,变为DOM结构。
function render(obj, root) {
const el = document.createElement(obj.tag);//创建结点
//如果已经到叶子节点了,就直接添加节点,建树
if (typeof obj.children === 'string') {
const text = document.createTextNode(obj.children);
el.appendChild(text);
}
//还没到叶子节点,就继续遍历
else if (obj.children) {
//递归调用,使用每一级的el作为root参数
obj.children.forEach((child) => render(child, el));
}
//后序遍历,将元素添加到root节点上
root.appendChild(el);
}
const obj = {
tag: 'div',
children: [
{ tag: 'span', children: 'hello world' }
]
}
//渲染到body下
render(obj, document.body);
编译时则需要编译的过程。可以给出一个compile函数来进行编译,而框架也可以从编译的过程中得到更多的信息,可以用于性能的优化。
vue同时支持编译时和运行时,保证了足够的灵活性。