简述dom diff原理

框架

浏览数:282

2019-4-19

前言:

关于react的虚拟dom以及每次渲染更新的dom diff,网上文章很多。但是我一直信奉一个原则,即:但凡复杂的知识,理解之后都只需要记忆简单的东西,而想简单、精确描述一个复杂知识,是极困难的事。

正文

dom diff是什么?
1.从根节点开始遍历所有节点;
2.对于不同类型的标签,删除原标签,新建标签;
3.对于类型相同、属性不同的标签,只修改属性;
4.对于同一个父节点下的复数同类型标签(即列表类型),基于key对比、修改。

解析

关于1:

-遍历用的是前序遍历(先序遍历)

关于2:

-不同类型的标签是指:比如div和span就是不同类型的标签
-如果同一个位置的标签类型改变(依然以div和span为例),那么直接删除div标签,新建一个span标签,重新渲染。原本的div标签里的一切都跟新的span标签没有关系
-对于自定义的组件比如<Header />、<TodoList />之类的也适用
-标签位置只相对于父节点有意义。假设原本A节点的父节点是B,更新后A节点的父节点是C,那么对于dom diff来说,原本的A节点会被销毁,在C节点下的A节点是一个新的节点,跟原本的A节点没有关系

关于3:

-这一个比较好理解,对于仅仅属性不同的标签,修改属性即可

关于4

-假设一个div下有五个span节点,此时我们要插入一个节点


虚拟dom并不知道插入后是ABFCDE,而会认为除了AB以外的节点都改变了
所以对于虚拟dom来说此时是ABGHIJ,付出了额外的消耗。
于是react引入了key的概念。两个key相同的节点,虚拟dom会认为是同一个节点,从而对其进行比较。引入了key之后,react就知道节点是ABFCDE了。