简述dom diff原理
前言:
关于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了。
相关推荐
Vue和React是数据驱动视图,如何有效控制DOM操作?能不能把计算,更多的转移为js计算?因为js执行速度很快。patch函数-->patch,对比tag,对比tag与key,对比children