• react性能优化


    1. 使用shouldComponentUpdate避免重复渲染

    以下代码,只有在count为3的时候才会触发更新

      class ClassChild extends React.Component {
        constructor() {
            super();
        }
        render() {
            console.log('classchild render');
            return <div>ClassChild</div>
        }
      }
    
      function FuncChild() {
        console.log('funcchild render');
        return <div>FuncChild</div>
      }
      export default class Page1 extends React.Component {
        constructor() {
            super();
            this.state = {
                count: 0,
            }
        }
    
        shouldComponentUpdate(nextProps, nextState) {
            if(nextState.count === 3) {
                return true;
            }
            return false;
        }
    
        add = () => {
            this.setState({
                count: this.state.count + 1
            });
        }
        
        render() {
            console.log('page1 render');
            return <div>
                <h1>Page1</h1>
                <button onClick={this.add}>add</button>
                <ClassChild></ClassChild>
                <FuncChild></FuncChild>
            </div>;
        }
    }
    

    大部分情况下,你可以使用React.PureComponent而不必写你自己的shouldComponentUpdate,它只做一个浅比较。但是当你比较的目标为引用类型数据,浅比较会忽略属性或状态突变的情况。

    class ClassChild extends React.PureComponent {
        constructor() {
            super();
        }
        render() {
            console.log('classchild render');
            return <div>ClassChild</div>
        }
    }
    

    如果是Function组件的话,你可以使用React.memo实现同样的效果:

    function Child() {
        console.log('funcchild render');
        return <div>FuncChild</div>
    }
    const FuncChild = React.memo(Child);
    

    2. 属性传递优化
    下面代码中,尽管ClassChild已经使用PureComponent优化了,count改变后还是会重新渲染ClassChild,是因为父组件更新后,执行render方法,ClassChild中传入的属性都是新的属性。

    class ClassChild extends React.PureComponent {
        render() {
            console.log('classchild render');
            return <div>ClassChild</div>
        }
    }
    export default class Page1 extends React.PureComponent {
        constructor() {
            super();
            this.state = {
                count: 0
            }
        }
        
        add = () => {
            this.setState({
                count: this.state.count + 1
            })
        }
    
        render() {
            return <div>
                <h1>Page1  count:{this.state.count}</h1>
                <button onClick={this.add}>add</button>
                <ClassChild style={{color: 'red'}}></ClassChild>
            </div>;
        }
    }
    

    因此最好将style属性提取到constructor中,如下:

    class ClassChild extends React.PureComponent {
        constructor() {
            super();
            this.style = {color: 'red'};
        }
        render() {
            console.log('classchild render');
            return <div>ClassChild</div>
        }
    }
    export default class Page1 extends React.PureComponent {
        constructor() {
            super();
            this.state = {
                count: 0
            }
        }
        
        add = () => {
            this.setState({
                count: this.state.count + 1
            })
        }
    
        render() {
            return <div>
                <h1>Page1  count:{this.state.count}</h1>
                <button onClick={this.add}>add</button>
                <ClassChild style={this.style}></ClassChild>
            </div>;
        }
    }
    

    3. 使用useCallback给函数做缓存

    以下代码每次改变count后,尽管ClassChild已经使用了React.PureComponent, ClassChild还是会重新进行渲染,那是因为父组件Page2每次进行更新的时候,声明的add方法都是个新的方法~

    import React, { useState, useCallback } from 'react';
    export default function Page2() {
        const [count, setCount] = useState(0);
    
        const add = () => {
            setCount(count+1);
        };
    
        return <div>
            <h1>Page2  count:{count}</h1>
            <button onClick={add}>add</button>
            <ClassChild add={add}></ClassChild>
        </div>;
    }
    

    因此需要使用useCallback对函数进行缓存,此时改变count,ClassChild不会重新渲染.(useCallback的第二个参数是依赖项,用法同useEffect,只有当依赖项变化后,才会产生新的方法)

    import React, { useState, useCallback } from 'react';
    export default function Page2() {
        const [count, setCount] = useState(0);
    
        const add = useCallback(() => {
            setCount(count+1);
        }, []);
    
        return <div>
            <h1>Page2  count:{count}</h1>
            <button onClick={add}>add</button>
            <ClassChild add={add}></ClassChild>
        </div>;
    }
    

    4. 使用useMemo给计算的值做缓存

    以下代码中,每次修改count后,expensive方法都会重新执行,这样会做很多无效的计算。

    import React, { useState, useMemo } from 'react';
    export default function Page2() {
        const [count, setCount] = useState(0);
        const [title, setTitle] = useState('hhh');
    
        const add = () => {
            setCount(count+1);
        }
    
        const expensive = () => {
            console.log('expensive函数执行');
            var sum = 0;
            for(let i = 0; i < 100000; i++) {
                sum++;
            }
            return `title是: ${title}`;
        };
    
        return <div>
            <h1>Page2  count:{count}</h1>
            <button onClick={add}>add</button>
            <ClassChild add={add} expensive={expensive()}></ClassChild>
        </div>;
    }
    

    而实际上expensive方法只需要在title变化的时候才需要重新计算,因此可以使用useMemo来给计算的值做缓存

    import React, { useState, useMemo } from 'react';
    
    class ClassChild extends React.PureComponent {
        constructor() {
            super();
        }
        render() {
            console.log('classchild render');
            return <div>ClassChild {this.props.expensive}</div>
        }
    }
    
    export default function Page2() {
        const [count, setCount] = useState(0);
        const [title, setTitle] = useState('hhh');
    
        const add = () => {
            setCount(count+1);
        }
    
        const expensive = useMemo(() => {
            console.log('expensive函数执行');
            var sum = 0;
            for(let i = 0; i < 100000; i++) {
                sum++;
            }
            return `title是: ${title}`;
        }, [title]);
    
        return <div>
            <h1>Page2  count:{count}</h1>
            <button onClick={add}>add</button>
            <ClassChild add={add} expensive={expensive}></ClassChild>
        </div>;
    }
    
  • 相关阅读:
    contab的使用方法
    mitmproxy安装与使用
    centos安装docker
    Linux安装python3.6
    Appium 教您完美win10安装Appium1.7.2支持win客户端自动化
    解决Git建立远程分支关联时fatal the current branch master has no upstream branch 问题
    git 命令上传远程服务器步骤
    robot打开浏览器WebDriverException: Message: WebDriver:NewSession
    jmeter线程组之间数据共享设置
    缓存的那些事
  • 原文地址:https://www.cnblogs.com/luoyanan/p/14951620.html
Copyright © 2020-2023  润新知