面试了许多求职者,很多求职者只知其然,而不知所以然,写此文章为广大前端小伙伴指引迷津。纯干货!纯干货!纯干货!
目录
Virtual DOM
什么是Virtual DOM?
答:将真实的DOM的数据抽取出来,以对象的形式模拟树形结构。
Virtual DOM的作用?
答:避免昂贵的DOM操作与大量无谓的计算量,通过diff算法,一边比较新旧节点一边给真实的DOM打补丁。
diff的原理?
React 分别对 tree diff、component diff 以及 element diff 进行算法优化。
-
tree diff
- React 通过 深度优先 对 Virtual DOM 树进行层级控制,只会对相同 DOM 节点进行比较,即同一个父节点下的所有子节点。
- 当发现节点已经不存在,则该节点及其子节点会被完全删除掉,不会用于进一步的比较。这样只需要对树进行一次遍历,便能完成整个 DOM 树的比较。
-
component diff
- 如果是同一类型的组件,按照原策略继续比较 virtual DOM tree。
- 如果不是,则将该组件判断为 dirty component,从而替换整个组件下的所有子节点。
- 对于同一类型的组件,有可能其 Virtual DOM 没有任何变化,如果能够确切的知道这点那可以节省大量的 diff 运算时间,因此 React 允许用户通过 shouldComponentUpdate() 来判断该组件是否需要进行 diff。
-
element diff
- 节点处于同一层级时,React diff 提供了三种节点操作,分别为:INSERT_MARKUP(插入)、MOVE_EXISTING(移动)和 REMOVE_NODE(删除)。
diff的比较方式?
答:前端操作dom的时候了,不会把当前元素作为上一级元素或下一级元素,很少会跨越层级地移动DOM元素,在采取diff算法比较新旧节点的时候,比较只会在同层级进行, 不会跨层级比较,因此复杂度的问题转换成 O(n) 复杂度的问题。
diff的弊端?
答:相同⽗元素的⼦元素必须有独特的 key,否则重复的 key 会造成渲染错误。
Vue vs React
- 相同点
- 都是两组虚拟dom的对比(react16.8之后是fiber与虚拟dom的对比)
- 只对同级节点进行对比,简化了算法复杂度
- 都用key做为唯一标识,进行查找,只有key和标签类型相同时才会复用老节点
- 遍历前都会根据老的节点构建一个map,方便根据key快速查找
- 不同点
- react会自顶向下全diff.
- vue会跟踪每一个组件的依赖关系,不需要重新渲染整个组件树。
- react在diff遍历的时候,只对需要修改的节点进行了记录,形成effect list,最后才会根据effect list 进行真实dom的修改,修改时先删除,然后更新与移动,最后插入
- vue 在遍历的时候就用真实dom
insertBefore方法,修改了真实dom,最后做的删除操作 - react 采用单指针从左向右进行遍历
- vue采用双指针,从两头向中间进行遍历
- react的虚拟diff比较简单,vue中做了一些优化处理,相对复杂,但效率更高