• [React] 性能优化相关 (二)


    1.避免使用内联对象

    使用内联对象时,react会在每次渲染时重新创建对此对象的引用,这会导致接收此对象的组件将其视为不同的对象。因此,该组件对于props的千层比较始终返回false,导致组件一直渲染。

    // Don't do this!
    function Component(props) {
      const aProp = { someProp: 'someValue' }
      return <AComponent style={{ margin: 0 }} aProp={aProp} />  
    }
    
    // Do this instead :)
    const styles = { margin: 0 };
    function Component(props) {
      const aProp = { someProp: 'someValue' }
      return <AComponent style={styles} {...aProp} />  
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    2.避免使用匿名函数

    虽然匿名函数是传递函数的好方法,但它们在每次渲染上都有不同的引用。类似于内联对象。

    为了保证作为props传递给react组件的函数的相同引用,如果使用的类组件可以将其声明为类方法,如果使用的函数组件,可以使用useCallback钩子来保持相同的引用。

    // 避免这样做
    function Component(props) {
      return <AComponent onChange={() => props.callback(props.id)} />  
    }
    
    // 函数组件,优化方法一
    function Component(props) {
      const handleChange = useCallback(() => props.callback(props.id), [props.id]);
      return <AComponent onChange={handleChange} />  
    }
    
    // 类组件,优化方法二
    class Component extends React.Component {
      handleChange = () => {
       this.props.callback(this.props.id) 
      }
      render() {
        return <AComponent onChange={this.handleChange} />
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    3.延迟加载不是立即需要的组件

    React.lazy和React.Suspense完成延迟加载不是立即需要的组件。React加载的组件越少,加载组件的速度越快。

    // React.lazy 接受一个函数,这个函数需要动态调用 import()引入组件
    const HomeIndex = React.lazy(() => import('@/modules/home'))
    ......
    
    // 然后应在 Suspense 组件中渲染 lazy 组件,如此使得我们可以使用在等待加载 lazy 组件时做优雅降级(如 loading 指示器等)
    return(
        <React.Suspense fallback={<>Loading...</>}>
            <HomeIndex />
        </React.Suspense>
    )
    
    
    // 一般会封装一个公共的方法
    const withLoadingComponent = (comp: JSX.Element) => (
      <React.Suspense fallback={<>Loading...</>}>
        {comp}
      </React.Suspense>
    )
    
    // 调用方法,传入要延迟加载的组件
    return(
    	{withLoadingComponent(<HomeIndex />}
    )
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    4.调整CSS而不是强制组件加载和卸载

    有时保持组件加载的同时,通过CSS隐藏可能是有益的,而不是通过卸载来隐藏。对于具有显著的加载或卸载时序的重型组件而言,这是有效的性能优化手段。

    将元素透明度调整为0对浏览器的成本消耗几乎为0(因为它不会导致重排),并且应该尽可能优先更改visibility或display。

    // 避免对大型的组件频繁对加载和卸载
    function Component(props) {
      const [view, setView] = useState('view1');
      return view === 'view1' ? <AComponent /> : <BComponent />  
    }
    
    // 使用该方式提升性能和速度
    const visibleStyles = { opacity: 1 };
    const hiddenStyles = { opacity: 0 };
    function Component(props) {
      const [view, setView] = useState('view1');
      return (
        <React.Fragment>
          <AComponent style={view === 'view1' ? visibleStyles : hiddenStyles}>
          <BComponent style={view !== 'view1' ? hiddenStyles : visibleStyles}>
        </React.Fragment>
      )
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    5.使用React.Fragment避免添加额外的DOM

    有些情况下,我们需要在组件中返回多个元素,例如下面的元素,但是在react规定组件中必须有一个父元素。

    	<h1>Hello world!</h1>
    	<h1>Hello there!</h1>
    	<h1>Hello there again!</h1>
    
    • 1
    • 2
    • 3

    为了减少不必要的加载时间,我们可以使React.Fragment来避免创建不必要的元素。

    function Component() {
            return (
                <React.Fragment>
                    <h1>Hello world!</h1>
                    <h1>Hello there!</h1>
                    <h1>Hello there again!</h1>
                </React.Fragment>
            )
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    6.使用React.PureComponent , shouldComponentUpdate

    父组件状态的每次更新,都会导致子组件的重新渲染,即使是传入相同props。但是这里的重新渲染不是说会更新DOM,而是每次都会调用diif算法来判断是否需要更新DOM。这对于大型组件例如组件树来说是非常消耗性能的。

    在这里我们就可以使用React.PureComponent , shouldComponentUpdate生命周期来确保只有当组件props状态改变时才会重新渲染。

    import React, { Component, PureComponent } from "react";
    
    // 没有变化不会触发render, 有变化触发render: 
    // 组件优化: 1.只要执行了setState, 都会触发render 2.触发render, 会render组件
    // 只有当前state和props数据发生改变的话才触发render
    // shouldComponentUpdate() 返回为 true
    export default class Parent extends Component {
      state = { count: 0 };
    
      // 重写 shouldComponentUpdate()
      shouldComponentUpdate(nextProps, nextState){
        if(this.state.count === nextState.count) return false
        else return true
      }
    
      // 如果修改的对象和以前的对象有一点联系的话, 不会触发render, 比如就修改对象的名称, 不修改对象的地址
      render() {
        const { count } = this.state;
        return (
          <div className="parent">
            Parent
            <br />
            {count}
            <button onClick={() => this.setState({ count: 1 })}>1</button>
            <Chird count={count} />
          </div>
        );
      }
    }
    
    class Chird extends PureComponent {
      // shouldComponentUpdate(nextProps, nextState){
      //   return !this.props.count === nextProps.count
      // }
    
      render() {
        return (
          <div className="child">
            Chird
            <br />
            {this.props.count}
          </div>
        );
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
  • 相关阅读:
    日常学习记录随笔-大数据之日志(hadoop)收集实战
    刷题笔记(js)
    mysql备份与恢复
    SpringBoot框架分层(View层、Controller层、Service层、Mapper层、pojo层)
    LeetCode977——有序数组的平方
    QT: 一种精确定时器类的实现与使用
    通常用哪些软件做数据可视化大屏?
    redis哨兵练习
    Bags Game
    HTML5-2-链接
  • 原文地址:https://blog.csdn.net/qq_43141726/article/details/133465002