Skip to content

Latest commit

 

History

History

commitPlacement

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 function commitPlacement(finishedWork) {
  // 先找到当前节点最近的父节点 这个节点一定是个HostComponent或HostRoot
  // 因为只有这两种才有对应的真实dom (其实还一种portal类型 暂且不论)
  let parentFiber = finishedWork.return
  while (!!parentFiber) {
    let tag = parentFiber.tag
    if (tag === HostComponent || tag === HostRoot) {
      break
    }
    parentFiber = parentFiber.return
  }

  let isContainer = null // 表示是否要挂载在根节点上
  let parent = null // 表示parentFiber对应的实例
  let parentTag = parentFiber.tag
  if (parentTag === HostComponent) {
    parent = parentFiber.stateNode
    isContainer = false
  } else {
    parent = parentFiber.stateNode.containerInfo
    isContainer = true
  }

  // 如果这个parent也需要重置文字内容
  // 那就要先执行resetTextContent给它做掉
  // 然后把这个ContentReset给去掉
  // if (parentFiber.effectTag & ContentReset) {}

  // 这个方法比较重要
  // 里头用了一个语法是:
  /*
    ding: while (xxx) {
      while (yyy) {
        // ...
        break ding
      }
      while (zzz) {
        continue ding
      }
    }
    这个语法的意思就是当while循环有嵌套的时候
    在内部的循环如果想直接break或continue的话
    只是单纯的跳出或者打断自己这个内部循环
    但是跳出外部的循环的话就可以通过这种语法直接跳出
  */

  // 找到一个节点before 要把新的节点插在这个before前面
  let before = getHostSibling(finishedWork)
  let node = finishedWork
  while (true) {
    let childTag = node.tag
    // 判断这个node是否是真实的dom节点或者text节点
    // 因为只有这两种节点才能被插入进dom
    if (childTag === HostComponent || childTag === HostText) {
      if (!!before) {
        // 如果有before说明找到了一个合适的真实兄弟dom
        // 那么就把它插在它前面
        parent.insertBefore(node.stateNode, before)
      } else {
        // 对于没有找到before的情况
        // 只能通过appendChlid去根据父元素
        // 把节点插入到父元素的最后一位了
        parent.appendChild(node.stateNode)
      }
    } else if (!!node.child) {
      // 如果当前这个需要Placement的节点
      // 是个classComponent之类的话
      // 就往下找 去找它的child
      // 它的child节点当中如果有节点需要插入的话 就重新执行对应的方法
      node.child.return = node
      node = node.child
      continue
    }
    if (node === finishedWork) {
      // 进入这里说明已经把子树都搞完了
      return
    }
    while (node.sibling === null) {
      if (node.return === null || node.return === finishedWork) {
        return
      }
      node = node.return
    }
    // 由于classComponent可能返回数组
    // 也就是说当前节点有兄弟节点
    // 它的兄弟节点也是需要插入到刚才那个before之前的
    // 所以要让当前节点node指向兄弟节点进行下一轮插入操作
    node.sibling.return = node.return
    node = node.sibling
  }
}