0

我一直在尝试理解反应协调,并且对差异算法如何工作的一些细节感到非常困惑。到目前为止,我了解到每当进行更新时,我们都会创建一个新的反应元素树并将其与我们之前的反应元素树进行比较。diffing 算法管理查找新旧反应元素树之间的差异。算法的 2 个假设。是相同级别和类型的元素不需要卸载和重新安装,并且键提供了一种不通过索引识别子元素的方法。

让我困惑的部分是如何在 2 个反应实例之间进行比较。例如,<Comp1/> 在旧的 React 元素树和<Comp2/>新的 React 元素树中进行比较时(假设在创建新树时<Comp2>被替换<Comp1>),差异算法是否只是比较两个 React 元素的“类型”属性?因此,如果两者具有相同的“类型”,那么差异算法不会考虑卸载和安装到 DOM 中?

4

1 回答 1

0

差异算法是否只是比较两个反应元素的“类型”属性?

是的,来自文档

每当根元素具有不同的类型时,React 都会拆除旧树并从头开始构建新树。从<a>to <img>,或 from <Article>to <Comment>,或 from <Button>to <div>——其中任何一个都将导致完全重建。

另一个你的问题:

因此,如果两者具有相同的“类型”,那么差异算法不会考虑卸载和安装到 DOM 中?

是的,在这种情况下,React 只是更新现有实例。在组件更新期间,实例保持不变,并且跨渲染保持状态。


您可以在下面的示例中看到:

  • 我们渲染的第一个地方,A当我们用另一个替换它时它不会被卸载A(因为相同的类型)。
  • 我们使用的第二个地方A,一旦我们替换它B,react unmounts A

let A = (props) => {
  React.useEffect(() => {
    console.log('Mounted A', props);
    return () => {
      console.log('Unmounted A', props);
    };
  }, []);
  return <div>This is A: {props.tmp}</div>;
};

let B = (props) => {
  React.useEffect(() => {
    console.log('Mounted B', props);
    return () => {
      console.log('Unmounted B', props);
    };
  }, []);
  return <div>This is B</div>;
};

  function App() {
  let [tmp, setTemp] = React.useState(0);
  return (
    <div
      onClick={() => {
        setTemp(tmp + 1);
      }}
    >
      {tmp % 2 == 0 ? <A id="first A"/> : <A id="second A"/>}
      {tmp % 2 == 0 ? <A id="third A"/> : <B />}
      <p>Start editing to see some magic happen :)</p>
    </div>
  );
}

ReactDOM.render(<App />,document.getElementById("react"));
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="react"></div>

于 2022-02-23T19:28:27.677 回答