React 组件实例的协调

发布于 2025-01-09 10:15:34 字数 454 浏览 3 评论 0原文

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

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

I've been trying to understand react reconciliation and am getting really confused by some of the details of how the diffing algorithm works. So far, I understand that whenever an update is made, we create a new react element tree and compare it with our previous react element tree. The diffing algorithm manages finding the difference between the new and old react element trees. The 2 assumptions of the algo. are that elements of the same level and type don't need to be unmounted and re-mounted and that keys provide a way of identifying child elements not by index.

The part that confuses me is how comparisons are made between 2 react instances. For example, when comparing <Comp1/> in the old react element tree and <Comp2/> in the new react element tree (assume that <Comp2> replaced <Comp1> in the creation of the new tree), does the diffing algorithm simply compare both react elements' "type" attributes? So if both have the same "type", then the diffing algorithm doesn't consider un-mounting and mounting into the DOM?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

清君侧 2025-01-16 10:15:34

比较算法是否简单地比较两个反应元素的“类型”
属性?

是的,来自文档

只要根元素有不同的类型,React就会拆掉
旧树并从头开始构建新树。从
,或从

另一个你的问题:

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

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


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

  • 我们渲染 A 的第一个位置,当我们将其替换为另一个 A 时(因为类型相同),它不会被卸载。
  • 我们使用 A 的第二个地方,一旦我们将其替换为 B,react 就会卸载 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>

does the diffing algorithm simply compare both react elements' "type"
attributes?

Yes, from the docs:

Whenever the root elements have different types, React will tear down
the old tree and build the new tree from scratch. Going from <a> to
<img>, or from <Article> to <Comment>, or from <Button> to <div> - any
of those will lead to a full rebuild.

Another your question:

So if both have the same "type", then the diffing algorithm doesn't
consider un-mounting and mounting into the DOM?

Yes, in that case React just updates the existing instance. During component update instance remains the same, and state is maintained across renders.


You can see in below example:

  • The first place where we rendered A, it doesn't get unmounted when we replace it also with another A (because of same type).
  • The second place where we used A, as soon as we replace it with 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>

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文