读书笔记-vue的设计和实现

110 阅读1分钟

第一篇

主要内容是介绍框架设计方面的知识,以及vue选择现在这些技术进行实现的原因

第一章 权衡的艺术

命令式和声名式

命令式和声名式是框架设计的两种范式。

其中,命令式注重过程,编写面向过程的代码,可以做到极致的性能优化(等于原生)。缺点是心智负担较大,且代码不易维护,特别是在大型的项目之中。

声名式则更注重代码结果,从具体的编写上来看就是html的树形结构和js操作dom的区别,声名式的编码更为直观,生产出来的代码也更易维护,缺点是性能可能较差。

性能与可维护性的权衡

结论:对web页面的编码,声名式的性能<=命令式的性能。

这里结合虚拟DOM进行解析。

我们在创建一个页面的时候:

  1. 可以通过直接操作DOM来得到页面,性能消耗为 innerHTML字符串+新建DOM元素
  2. 通过声名式来得到页面,性能消耗为 新建JS对象 + 新建所有DOM元素

这样来看,在新建页面的时候,命令式的操作一定会有更好的性能。

更新页面的时候:

  1. 每一个微小的更新都会导致所有的DOM节点的销毁和重建,消耗:重新渲染+新建
  2. 根据算法来找到需要更新的DOM节点进行更新,消耗:找到节点+更新对应节点

在不同的情况下,两种方法的效率不同。但在大部分情况下,使用声名式代码进行更新的效率会更高

虚拟DOM的性能

虚拟DOM的性能可以根据上面两种情况进行推断。这里进行权衡的指标主要是三个:心智负担、性能、可维护性

我们常用的三种渲染页面的方法:

  1. 直接使用innerHTML进行渲染。----心智负担适中、性能差、可维护性一般(在大型项目中)
  2. 使用虚拟DOM进行渲染。 ----心智负担小,性能可以接受,可维护性好
  3. 纯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同时支持编译时和运行时,保证了足够的灵活性。