【问题标题】:How does the react library rerender componentsreact 库如何重新渲染组件
【发布时间】:2020-05-28 11:42:41
【问题描述】:

我试图弄清楚在更新props 后反应库如何重新呈现组件。因此,我有点猴子修补了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'))
  })
}

这适用于第一个渲染周期。但是在渲染组件的props 更改后,console.logs 不再打印。为了弄清楚为什么我在文档中读到 ReactDOM.render 只会被称为 once。所以我通过谷歌搜索,就像通过 react 的来源一样,但我无法找出 react 如何在道具更新后重新渲染组件。你能帮帮我吗?

【问题讨论】:

  • “如何”是什么意思?你读过文档吗?你在说Reconciliation吗?你期待什么样的答案?
  • @DennisVash 非常感谢你,是的,我谈论的是Reconciliation。在最好的情况下,我很想找到实现这种协调的源代码。我阅读了文档,也发现了一些关于它的内容,但不完全是我正在搜索的内容

标签: javascript reactjs


【解决方案1】:

ReactDom.render 调用一次以将组件挂载到 DOM 中。

在状态更新或 props 更改时,React 启动 Reconciliation 过程。

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

在这个过程中,React 在遍历 Virtual 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++
  }
}

【讨论】:

    猜你喜欢
    • 2020-09-29
    • 2021-06-19
    • 2018-04-22
    • 1970-01-01
    • 2019-11-20
    • 2016-01-11
    • 2020-05-01
    • 2018-03-24
    相关资源
    最近更新 更多