likes
comments
collection
share

深入理解React中的虚拟Dom和Fiber

作者站长头像
站长
· 阅读数 15

什么是虚拟Dom

个人理解来说它是一个JS对象对象内有某个DOM的详细信息,比如说当前节点对象的id class等,当某个元素发生变化的时候,比如说它的message、ID、Class就会重新遍历渲染当前这个节点对象,而不是整个所有的Dom结构重新渲染

虚拟Dom和普通Dom节点不同之处

直接操作普通Dom

之前用过原生JS和jQuery开发,都是直接操作Dom节点,但是直接操作缺点非常明显,因为用户直观看到的是整个Dom节点,如果直接进行操作,没有经过计算,并且操作过多,则页面会一直闪来闪去、刷新白屏体验极差!

如何优化

既然修改的时候要发生状态变更,那就可以计算前后两次变更的具体地方,从而计算出最少的一个操作值这样对Dom操作是最少的,对用户体验和影响也是最小的。

为什么要用虚拟Dom

说到计算两个前后变更的地方,直接计算Dom节点也可,但是一个节点就会有几十几百的属性值,如果一一对比则计算量庞大浪费资源,直接构建虚拟Dom对象,只计算重要的属性值,成本低很多

import {React} from 'react'
const test = (
    <div className = 'box-border'>
        <h1></h1>
        <h2></h2>
        <FunctionComponent name='组件' />
    </div>
)

在React中写JSX语法的时候用到Dom,它会编译成一个对象,这就是虚拟Dom,在React16中通过babel-loader进行编译,需要通过 import引入react,在Reatct17提供了自动引入,不需要每次手动引入

Fiber

fiber是在react16之后出现,在React16之前,开发组件和页面多,相应的Dom结构也会非常复杂

export function updateHostCompoent(wip){
  if(!wip.stateNode){
    wip.stateNode = document.createElement(wip.type)
  }
  reconcileChildren(wip,wip.props.children)
}

如果使用虚拟Dom来进行更新,则需要遍历,但是成本较高因为需要一个一个来遍历,如果在某一个遍历时间较长,很有可能会造成阻塞

为什么需要Fiber

Fiber它是一个JS对象来描述虚拟的Dom节点

  1. 分级别进行处理,也就是把多个渲染任务的多个模块进行拆分
  2. 能够随时进行暂停、终止计算 总结来说,它是一个链表结构,给每个Dom节点给予不同的级别,通过循环来分别对比
function reconcileChildren(returnFiber,children){
  const newChildren = isArray(children) ? children : [children]
  for(let i =0;i<newChildren.length;i++){
    const newChild = newChildren[i]
    const newFiber = createFiber(newChild,returnFiber)
    if(i == 0){
      returnFiber.child = newFiber
    }else{
      proviousNewFiber.sibling = newFiber
    }
    proviousNewFiber = newFiber
  }
}

newChildren是当前节点的子节点对象,根据它来进行判断和循环遍历,如果它为空,则当前这个子节点就是新节点,反之则是新节点