虚拟DOM
在这三个框架中(vue,react),都是使用虚拟DOM来提高效率的,那么来说说什么是虚拟DOM?为什么要用?还有它是怎么工作的?
什么是DOM
浏览器中的一个概念,用JS对象来表示页面上的元素,并提供用于操作DOM对象的API
DOM树
一个网页呈现的概念
网页呈现的过程:
- 浏览器请求服务器获取页面HTML代码
- 浏览器要先在内存中解析DOM结构,并在浏览器内存中渲染出一个DOM树
- 浏览器把DOM树呈现在页面上
为什么原生JS会浪费性能?
举个例子:
我要更新10个DOM节点,浏览器会一个一个的进行更新,但它更新第一个的时候并不知道后面还有9个,所以会一个一个执行,共执行10次。每一次的更新都要去计算,但更新后DOM树变化了,更新第二个的时候,前一次计算的就没法再利用了,还需要再计算。白白浪费性能。
什么是虚拟DOM?
框架中的概念,用JS对象来模拟页面上DOM和DOM之间的嵌套,本质是一个对象,而且把原生对象中的属性根据需要添加,不是全部存在,更‘轻’。
工作原理
获取内存中的(虚拟)dom树
和新生成的(虚拟)dom树
,通过diff算法进行对比,得到需要更新的DOM元素
这两颗(虚拟)DOM树
都是框架模拟出来的,就是个对象,旧的会被保存在内存中
为什么虚拟DOM性能更优秀?
还是要更新10个DOM节点,虚拟DOM
不会一次一次的去通知浏览器,而是通过diff算法
去操作框架造出来的虚拟DOM树
(也就是个对象),更新对象速度会很快,然后将修改后的虚拟DOM树
一次性的让浏览器进行挂载更新,减少计算的浪费。
这么一比较,浏览器只是运作了一次,达到高效的更新渲染
什么是diff算法?
分成三部分tree diff
component diff
element diff
,分别去对比新旧(虚拟)dom树
,DOM树中的组件,组件中的元素
tree diff
新旧两个DOM树,逐层对比的过程,就是tree diff
当整个DOM树逐层对比完毕,则能找到要被更新的元素
component diff
在进行tree diff
的时候,会对每一层的组件进行对比,如果新旧组件的类型相同,会进行element diff
对比,如果不同,直接移除组件更新新组件
element diff
在进行component diff
对比时如果两个组件的类型相同,会对其内部的元素进行对比
总结
在对比整个DOM树时,先对比页面中的DOM树内容是否有变化,然后对比组件是否一致,不一致的替换,一致的对比组件累的元素是否一致。有次,可以不漏下每一个元素,完成更新
但是,当循环的时候,设置key值有问题会导致diff算法对比失误,下章详解key值得作用,为什么不能使用index当key?