了不得的Virtual DOM(一):起源

前言

  首先欢迎你们关注个人掘金帐号和Github博客,也算是对个人一点鼓励,毕竟写东西无法得到变现,能坚持下去也是靠的是本身的热情和你们的鼓励。html

  之因此想写本系列文章的主要缘由是将近一个月时间没有写点东西了,加上最近各类事情特别多使得我没有过多的时间研究本身喜欢的东西。前段时间看到大神livoras的博客,关于Virtual DOM的讲解的很是透彻,因为本身从事React开发,也算是Virtual DOM的使用者,因此萌发了写关于Virtual DOM的系列文章,而且也想尝试本身实现一套Virtual DOM。所以本系列文章会围绕这Virtaul DOM这个话题作一系列的分析甚至也会尝试着和你们一块儿实现本身的Virtual DOM 框架,感兴趣的同窗能够关注的个人掘金帐号或者关注个人Github博客
  前端

框架回顾

  首先听到Virtual DOM这个概念应该来自于React,而且在不了解时以为这个概念是一个逼格特别高的词。其实任何技术的诞生都是有相应的历史的,没有任何事物是凭空出现的,就像我听到不少人诟病JavaScript语言的语法糟粕太多,但实质上你要了解到JavaScript出现的缘由和它的做者Brendan Eich仅仅用了十几天就设计出一门普遍流行的高级语言,你必定不会这样想。一样的,Virtual DOM的出现也是有必定的历史缘由的,这就不得不讲到前端框架的历史了。
  
  其实全部框架所能作到的事情咱们手动均可以实现,对于咱们在大学课堂(固然有的学习并无开设相关的课程)的学习JavaScript时候,想用JavaScript建立一个表单验证的程序时,十几行代码就能搞定,这时候框架这种东西对你是臃肿的、没有必要的。甚至框架会极大的提升你的学习成本、下降你程序的运行速度(框架并不能保证效率必定高于你的手动操做)。可是当你的程序规模逐渐增大,你会发现你的代码数量会指数级膨胀,甚至一个js文件中会有上万行的代码(不要惊讶,我真的见过这场常见),这时候维护这套代码将是一场灾难。
  
  这时候各类前端框架就应用而生了,框架出现的目的并非为了提高性能,而是为了可维护性、为了便于团队开发。可是天下没有白吃的午饭,你为了程序的可维护性,出让了一部分性能做为妥协,毕竟什么框架都没有手动原生操做性能高,由于框架要具备适普性,要能处理各类各样的场景。
  git

MVC

  其实对于前端所须要的作的就是展现数据的界面(View)以及在界面的更改能触发相应的数据(Model)变化,而且数据(Model)发生改变时界面(View)也能及时响应并作相应的变化。说到底就是如何协调View与Modal的关系。
  
  
  早期出现相似于Backbone的框架就是典型的MVC(其实我也并无经历过这个年代)。经过在View与Model设置Controller层,这样用户交互触发的操做都会转交给Controller,由Controller层控制相应的改变Model的数据。在Model数据发生改变时,会经过观察者模式去通知对应的View,而后View从新请求Model数据作相应的界面改变。
  
  随着应用规模的增长你会发现MVC模式会存在几个显著的问题,Model与View的对应关系是多对多的,可能一个Model会对应多个View或者一个View对应多个Model,甚至更加复杂的场景,Model与View之间错综复杂的关系使得开发的难度增长。而且因为View是依赖于Model的,所以想要在这种模式下实现视图的组件化是相对比较难的。
  github

MVP  

  咱们并不但愿View和Model之间依赖的这么紧,因此咱们能够改进MVC模式,就出现了MVP模式。
  
  
  
  MVP是MVC的改进版本,将MVC中的Controller改成Presenter,用户交互触发的操做会转交给Presenter处理。而后会由Presenter控制改变相应Model的改变。到此为止Presenter所承担的操做与Controller很是相近,可是为了让Model与View相互独立,Model改变后的通知是分发给Presenter,Presenter收到Model改变的通知就会调用View的接口来改变用户界面。
  
  这样咱们经过Presenter就实现了Model和View的相互独立,只要View与Model之间预留好所须要的接口,两者互相是没有影响关系,互相是透明的,在这个基础上,咱们要实现View的组件化是很是容易的。可是这种模式也并非没有缺点,Presenter的逻辑不只须要承担以前Controller的全部功能,并且还须要接受Model数据改变的通知并按照对应的功能改变用户界面,这就使得Presenter所要承担的功能过于多,使得Presenter太臃肿、难以维护。
  算法

MVVM

  咱们发现MVP也有相应的缺点,所以前人在MVP的基础上作了改良,出现了MVVM的结构。
  
  
  
  咱们看到MVP的缺点主要是Presenter过于庞大,其实Model改变通知Presenter而且Presenter改变View这条逻辑并非必定须要手动控制,其实对应的Model变化引发对应固定的View改变的规则通常来说是不变的,那这一部分逻辑就能够释放出来由引擎自动处理。MVP按照这个思路进行改良,将原来的Presenter进化为View Of Model(VM:视图模型),视图模型中包含Binder(或者说是Data-binding engine),负责View与Model的双向绑定。在编写View时可使用声明式的指令将View与对应的Model进行绑定。ViewModel在对应Model进行改变时能够自动更新View,同理View发生改变时,ViewModel也会对应Model的数据,这也就是咱们一般所讲双向数据绑定(Two-way data-binding)。
  
  MVVM的优势很是显然,极大的提升了可维护性,View与Model之间的相互手动维护更新被释放,改成自动更新。可是因为ViewModel的构建和维护成本相对较高,对于一些简单的页面并不适用,对于复杂的视图却又带来了性能成本。
  缓存

换一种思路解决

  到此为止咱们了解了MV*类型的框架是如何解决Model层与View层链接的,经过在Model与View之间构建各类中间层(Controller、Presenter、View of Model)来处理二者之间的同步关系。可是咱们能不能换一种思路,View能够当作Model对应必定规则的视图表示,所以当Model发生改变时直接从新渲染View
  
  咱们不由感到这种操做方式真是骚啊!
  
  
  
  这种方法行不行?固然!其实React的整体思路不就是这种吗?可是经验丰富的你必定会马上质疑这东西性能靠谱吗?事实上,若是Model改变引发的View改变很是大(譬如全部的界面都改变了),这种模式反而性能会很好,由于自己的界面改变就等同于从新渲染。可是若是当前的Model改变只会引发界面一个很是细微的变化(例如某个按钮的颜色发生改变),咱们就从新刷新整个界面,那实在是太恐怖了。
  
  搞过前端的同窗必定都明白DOM的速度相比于JavaScript的简直就是龟速,由于DOM的属性、结构自己就设计的很是复杂。那这种方式是否是就彻底能够废弃呢?
  
  不是!不然React就不会出现。
  
  大学学习过计算机组成原理的同窗应该还记的,CPU的计算速度是很是快,可是相比于CPU,其余的IO部件,例如硬盘,速度是很是低的,差的都不是一个数量级的问题。这时候计算机就引入了RAM,RAM的速度低于CPU可是却高于硬盘,对于CPU所需的数据,能够先从硬盘放入RAM,而后CPU运算的结果也放入RAM中,若是须要数据的永久化存储时才会存入硬盘中。甚至CPU会以为RAM速度仍是慢,在CPU内部引进了各级Cache,来解决RAM与CPU之间的性能瓶颈。
  
  前端就能够借鉴这种思惟方式,DOM是低速的,但JavaScript性能确实至关的不错,尤为在拥有V8引擎的今天。那么咱们就能够用JavaScript来描述DOM结构,相似于下面的结构:
  
前端框架

其实所描述的DOM结构就是下面的样子:框架

<div>
    <button>按钮</button>
</div>

  固然这种表示方法并不惟一,只要能描述清对应的DOM结构,你能够随意发挥。
  
  这样在每次Model改变以后,咱们首先能够拿到本次Model的对应的Virtual DOM结构,它表明的就是本次Model对应View的DOM结构。若是咱们还在程序中缓存了上次Model对应的Virtual DOM结构,那么咱们就能够去比较先后两个Virtual DOM结构,采用必定的算法,得出两个Virtual DOM的不一致的地方,这个算法就是咱们一般所讲的Diff算法。而后用最优的方法将两个Virtual DOM的差别应用的真实DOM上。
  
  那这种方式必定是高于咱们最开始所讲的从新渲染的思路吗?固然不是,若是界面变化很是大,那么咱们以前所讲的Virtual DOM性能可能就低于从新渲染,由于Diff的过程也是有性能损耗了,即便在React采用了各类启发式算法将两个Virtual DOM树形结构由O(n ^ 3)降到了O(n)的状况下,在节点很是多的状况下,Diff的代价也是要被考虑的。
  组件化

总结

  本篇文章咱们大体环顾了各类MV*框架的改进历史,从而讲述了React所提出的另外一套新颖的解决思路,而且为何React会引入Virtual DOM的缘由。读到这里可能对你了解Virtual DOM有了些许帮助,欢迎你们关注个人博客,之后会继续更新Virtual DOM的系列文章以及其余我在前端学习中感悟。若有不正确的地方,欢迎各位赐教。
  
  
  性能

相关文章
相关标签/搜索