发展过程
谈论页面的变化之前,咱们先看下数据和页面(视觉层面的页面)的关系。数据时隐藏在页面底下,通过渲染展示给用户。同样的数据,按照不同的页面设计和实现,会以不同形式、样式的页面呈现出来。有时候在一个页面内的不同位置,也会有相同数据的不同表现。
Web的早期,这些页面通常是静态的,页面内容不会变化。而如果数据发生了变化,通常需要重新请求页面,得出基于新的数据渲染出的新的页面。
至少,这个模式理解起来挺简单不是吗。
直到Web应用复杂起来,开发者开始关注用户体验,开始将大量的处理向前端迁移,页面变得多态、灵活起来。一个显著的特征是,数据发生变化之后,不再需要刷新页面就能看到页面上的内容随之更新了。
前端需要做的事情变得多了起来,前端工程师们也就修炼了起来,各种前端技术也就出现了。
首先,聪明的工程师们发现既然是在前端渲染页面,如果只是部分数据发生了变化,就要把页面整体或一大块区域重新渲染就有点笨了。为什么不把事情做得更极致些,只更新变化的数据对应的页面的内容呢?
怎么做呢?操作 DOM 呗。DOM 就是浏览器提供给开发者用于操作页面的模型嘛,直接通过脚本来调用 DOM 的各种接口就 OK 了。而且我们还有了像 jQuery 这样的棒棒的工具,操作 DOM 变得 so easy。
然而,页面越来越复杂,聪明的工程师们发现数据变化之后,老是需要手动编程去操作对应的DOM节点执行更新,有点烦,不够懒啊。于是各种框架如雨后春笋出现了,纷纷表示可以简化这个过程。
稍微早期的框架有这样的:
开发者借助框架,监听数据的变更,在数据变更后更新对应的DOM节点。虽然还是要写一些代码,但是写出来的代码好像很有条理的样子,至少更容易理解和维护了,也不错嘛。
更进一步,MVVM框架出现了,以AngularJS为代表:
仍然是数据变化后更新对应DOM节点的方式,但是建立这种绑定关系的过程被框架所处理,开发者要写的代码变少了,而且代码更易读和维护了。
再然后呢,大家就在这个棒棒的模式上继续深耕,纷纷表示还可以在性能上做的更好,前端领域一片繁荣。
再后来React出现了,它不仅不是MVVM框架,甚至连MV框架都不是。这年头,不是个MV框架还好意思出门?React还真的带来了新的思路!
什么思路呢?
就是回到过去,回到那个简单而美好的时候。具体而言,就是每次数据发生变化,就重新执行一次整体渲染。的确这样更简单,不用去琢磨到底是数据的哪一部分变化了,需要更新页面的哪一部分。但是坏处太明显,体验不好啊。而React给出了解决方案,就是Virtual DOM。
VIrtual DOM概况来讲,就是在数据和真实DOM之间建立了一层缓冲。对开发者而言,数据变化了就调用React的渲染方法,而React并不是直接得到新的DOM进行替换,而是先生成Virtual DOM,与上一次渲染得到的Virtual DOM进行对比,在渲染得到的Virtual DOM上发现变化,然后将变化的地方更新到真实DOM上。
简单来说,React在提供给开发者简单的开发模式的情况下,借助Virtual DOM实现了性能上的优化,以致于敢说自己”不慢“。
Virtual DOM
React基于Virtual DOM的数据更新与UI同步机制:
初始渲染时,首先将数据渲染为Virtual DOM,然后由Virtual DOM生成DOM。
数据更新时,渲染得到新的Virtual DOM,与上一次得到的Virtual DOM进行diif,得到所有需要在DOM上进行的变更,然后在patch过程中应用到DOM上实现UI的同步更新。
Virtual DOM作为数据结构,需要能准确地转化为真实DOM,并且方便进行对比。