React库如何重新呈现组件

时间:2020-05-28 11:42:41

标签: javascript reactjs

我正在尝试弄清更新props之后react库如何重新渲染组件。因此,我有点像ReactDOM.render这样的猴子修补方法:

const oldRender = ReactDOM.render

ReactDOM.render = function(){
// ......
console.log("42")
  return oldRender.call(this, ...arguments, () => {
    console.log("done")
    document.dispatchEvent(new Event('react-dom-rendered'))
  })
}

这适用于第一个渲染cylce。但是,在更改呈现组件的props之后,console.log将不再打印。为了弄清楚为什么我在文档中读到ReactDOM.render仅被称为一次。所以我像通过react的来源一样搜索了google,但是我无法找出props更新后react如何重新渲染组件。你能帮我吗?

1 个答案:

答案 0 :(得分:2)

ReactDom.render调用一次,以将组件安装到DOM中。

在状态更新或道具更改时,React启动对帐过程。

当组件的属性或状态发生变化时,React通过将新返回的元素与先前渲染的元素进行比较来确定是否需要实际的DOM更新。当它们不相等时,React将更新DOM。这个过程称为“和解”。

在此过程中,React在遍历虚拟DOM副本时运行非常简单的diff algorithm

是否要实施和解?参见Build your own React及其repo

function reconcileChildren(wipFiber, elements) {
  let index = 0
  let oldFiber =
    wipFiber.alternate && wipFiber.alternate.child
  let prevSibling = null

  while (
    index < elements.length ||
    oldFiber != null
  ) {
    const element = elements[index]
    let newFiber = null

    const sameType =
      oldFiber &&
      element &&
      element.type == oldFiber.type

    if (sameType) {
      newFiber = {
        type: oldFiber.type,
        props: element.props,
        dom: oldFiber.dom,
        parent: wipFiber,
        alternate: oldFiber,
        effectTag: "UPDATE",
      }
    }
    if (element && !sameType) {
      newFiber = {
        type: element.type,
        props: element.props,
        dom: null,
        parent: wipFiber,
        alternate: null,
        effectTag: "PLACEMENT",
      }
    }
    if (oldFiber && !sameType) {
      oldFiber.effectTag = "DELETION"
      deletions.push(oldFiber)
    }

    if (oldFiber) {
      oldFiber = oldFiber.sibling
    }

    if (index === 0) {
      wipFiber.child = newFiber
    } else if (element) {
      prevSibling.sibling = newFiber
    }

    prevSibling = newFiber
    index++
  }
}