经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » JS/JS库/框架 » React » 查看文章
React 组件的状态下移和内容提升的操作方法
来源:jb51  时间:2022/11/28 8:56:05  对本文有异议

前言

本专栏的另一篇文章,讲到了 useMemo 有一定的开销,不能滥用,本篇文章讲解两个简单实用的优化组件渲染性能的方法:

  • 状态下移
  • 内容提升

在讲解这两种方法之前,我们需要先手动创建一个有严重渲染性能的组件,如下所示:

  1. import { useState } from 'react';
  2.  
  3. export default function App() {
  4. let [color, setColor] = useState('red');
  5. return (
  6. <div>
  7. <input value={color} onChange={(e) => setColor(e.target.value)} />
  8. <p style={{ color }}>Hello, world!</p>
  9. <ExpensiveTree />
  10. </div>
  11. );
  12. }
  13.  
  14. function ExpensiveTree() {
  15. let now = performance.now();
  16. while (performance.now() - now < 100) {
  17. // Artificial delay -- do nothing for 100ms
  18. }
  19. return <p>I am a very slow component tree.</p>;
  20. }

很显然,当 App 组件内的状态发生了改变,ExpensiveTree 组件会 re-render, 事实上 ExpensiveTree 组件的 props、state 并未发生改变,这并不是我们期望的结果,下面将提供两种简单的方法,提升组件渲染的性能;

状态下移

  1. export default function App() {
  2. let [color, setColor] = useState('red');
  3. return (
  4. <div>
  5. <input value={color} onChange={(e) => setColor(e.target.value)} />
  6. <p style={{ color }}>Hello, world!</p>
  7. <ExpensiveTree />
  8. </div>
  9. );
  10. }

我们可以看到以上 ExpensiveTree 组件并不依赖 App 组件内部的状态,因此我们是否可以考虑,将依赖 color 的元素抽离到一个依赖 color 的组件中呢?
下面是实践后的代码:

  1. export default function App() {
  2. return (
  3. <>
  4. <Form />
  5. <ExpensiveTree />
  6. </>
  7. );
  8. }
  9.  
  10. function Form() {
  11. let [color, setColor] = useState('red');
  12. return (
  13. <>
  14. <input value={color} onChange={(e) => setColor(e.target.value)} />
  15. <p style={{ color }}>Hello, world!</p>
  16. </>
  17. );
  18. }

此时,将依赖 color 的元素提取到了 Form 组件中,Form 组件内部的状态不再影响 ExpensiveTree 组件的渲染,问题便得到了解决

内容提升

  1. export default function App() {
  2. let [color, setColor] = useState('red');
  3. return (
  4. <div style={{ color }}>
  5. <input value={color} onChange={(e) => setColor(e.target.value)} />
  6. <p>Hello, world!</p>
  7. <ExpensiveTree />
  8. </div>
  9. );
  10. }

以上情况是高开销组件 ExpensiveTree 的父节点依赖 color,此时显然状态下移是行不通的,但是还有另外一种办法:

  1. export default function App() {
  2. return (
  3. <ColorPicker>
  4. <p>Hello, world!</p>
  5. <ExpensiveTree />
  6. </ColorPicker>
  7. );
  8. }
  9.  
  10. function ColorPicker({ children }) {
  11. let [color, setColor] = useState("red");
  12. return (
  13. <div style={{ color }}>
  14. <input value={color} onChange={(e) => setColor(e.target.value)} />
  15. {children}
  16. </div>
  17. );
  18. }

此时和状态提升是完全相反的,将依赖 color 的元素提升到了 ColorPicker 组件中,而不依赖 color 的元素以 children prop 的形式传入了 ColorPicker ,当组件内部的状态改变时:

  • ColorPicker 会重新渲染但是它仍然保存着
  • ColorPicker 的 children 属性未变化 React 并不会访问那棵子树。 因此,ExpensiveTree不会重新渲染。

本文提供的方法并不是新的创意,大家一定都有所实践,但是我想表达的是,相比于滥用 useMemo,我们需要首先考虑使用这两种提高组件渲染性能的方法;

到此这篇关于React 组件的状态下移和内容提升的文章就介绍到这了,更多相关React 组件状态下移内容请搜索w3xue以前的文章或继续浏览下面的相关文章希望大家以后多多支持w3xue!

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号