温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

React中immutable的UI组件渲染性能是什么

发布时间:2023-04-17 17:37:37 来源:亿速云 阅读:111 作者:iii 栏目:开发技术

本篇内容主要讲解“React中immutable的UI组件渲染性能是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“React中immutable的UI组件渲染性能是什么”吧!

    引言

    react 一直遵循UI = fn(state) 的原则,有时候我们的state却和UI不同步 有时候组件本身在业务上不需要渲染,却又会再一次re-render。

    UI组件渲染性能

    react每次触发页面的更新可大致分成两步:

    • render(): 主要是计算v-dom的diff

    • commit阶段 :将得到的diff v-dom一次性更新到真实DOM

    一般我们讨论的渲染 指的是第一步, 我可以悄悄的告诉你 第二步我们也管不了,什么时候更新真实DOM, React有一套自己的机制

    组件渲染分为首次渲染和重渲染,首次渲染不可避免就不讨论 重渲染指当组件state或者props发生变化的时候造成的后续渲染过程,也是本文的讨论重点

    其实React 在更新组件这方面 一直都有一个诟病 就是:

    父组件重渲染的时候,会递归重渲染所有的子组件

    const List = () => {
      const [name, setName] = useState<string>("");
      // 用来测试的其它状态值
      const [count, setCount] = useState<number>(0);
      const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
        const val = e.target.value;
        setName(val);
      };
      const handleClick = () => {
        setCount((c) => c + 1);
      };
      return (
        <main>
          <div className="list">
            <input value={name} onChange={handleInputChange} />
            <button onClick={handleClick}>测试</button>
            <Child count={count} />
          </div>
        </main>
      );
    };
    const Child: React.FC<any> = (props) => {
      console.log("Child has render");
      return <p>count:{props.count}</p>;
    };

    React中immutable的UI组件渲染性能是什么

    当 Input name改变的时候 List触发rerender Child会发生rerender 可是Child 依赖的props只有count而已, 如果所有的子组件都被迫渲染,计算在render花费的时间和资源有可能成为性能瓶颈.

    方案一:shallow compare

    React其实刚出来就提供了优化的手段:

    • shouldComponentUpdate: 返回false 就直接跳过组件的render过程

    • React.PureComponent: 对props进行浅比较,如果相等 则跳过render 用于class 组件

    • React.memo: 也是进行浅比较,适用于functional Component

    本文设计的组件以functioal component为主 因为后面会涉及到hooks的使用,对上述例子修改:

    const Child: React.FC<any> = React.memo((props) => {
      console.log("Child has render");
      return <p>count:{props.count}</p>;
    })

    React中immutable的UI组件渲染性能是什么

    很好 child没有跟着name重渲染了,如果props是一个对象呢?

    const List = () => {
      const [name, setName] = useState<string>("");
      // 用来测试的其它状态值
      const [count, setCount] = useState<number>(0);
      console.log(count)
      const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
        const val = e.target.value;
        setName(val);
      };
      const handleClick = () => {
        setCount((c) => c + 1);
      };
      const item: IItem = {
        text: name,
        id: 1,
      };
      return (
        <main>
          <div className="list">
            <input value={name} onChange={handleInputChange} />
            <button onClick={handleClick}>测试</button>
            <Child  item={item} />
          </div>
        </main>
      );
    };
    const Child: React.FC<{ count?: number; item: IItem }> = React.memo(
      ({ item }) => {
        console.log("Child has render");
        return <p>text:{item.text}</p>;
      }
    );

    改变name时候Child会改变 这是预期内的 而当改变count时,Child还是会重渲染,这是什么原因呢?因为count改变后 List组件会rerender 从而导致导致 item这个对象又重新生成了 导致child每次接受的是一个新的object对象 由于每个literal object的比较是引用比较 虽然前后属性相同,但比较得出的结果为false,造成 Child rerender 。

    浅比较一定要相同引用吗?不一定,一般的面试中浅比较只是对值的比较 但是React.memo中要求引用类型一定要相同 为什么呢?我猜是出于对性能的考虑,不用深比较也是为了节约性能 通常情况下 我们想要的UI对应的是每个叶子节点的值 ,即只要叶子节点的值不发生变化 就不要rerender

    方案二:直接对前后的对象进行deepCompare

    还好React.memo有第二个参数可以使用

    const Child: React.FC<{ item: IItem }> = React.memo(
      ({ item }) => {
        console.log("Child has render");
        return <p>text:{item.text}</p>;
      },
      (preProps, nextProps) => {
        return _.isEqual(preProps, nextProps); // lodash的深比较 
      }
    );

    保证引用相等的情况下,值也相等 useRef

      const item: MutableRefObject<IItem> = React.useRef({
        text: name,
        id: 1,
      });
    <Child item={item.current} />

    好家伙,name无论怎么变化 Child 始终不会更新,useRef保证了返回的值是一个MutableObject 不可变的,意思就是引用完全相同 不管值变化 就不会保持更新.导致了UI不一致,那么我们怎么保证 name 不变的时候 item 和上次相等,name 改变的时候才和上次不等。useMemo

      const item: IItem = React.useMemo(
        () => ({
          text: name,
          id: 1,
        }),
        [name] // name变化触发item不等 name不变item和上次相同
      );

    到此,相信大家对“React中immutable的UI组件渲染性能是什么”有了更深的了解,不妨来实际操作一番吧!这里是亿速云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

    向AI问一下细节

    免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

    AI