React生命周期shouldComponentUpdate介绍及性能优化

React生命周期shouldComponentUpdate介绍及性能优化

在react开发中,经常需要对数据state状态进行改变,但是这种方式每当setState的时候都会将所有的组件重新渲染一遍,这样就会有重复渲染render的问题。

看如下图组件树:

默认情况下,当执行setState()方法时,react 会重新渲染整个组件树,这造成不必要的性能开销。
黄色的节点表示我们修改了数据的节点,我们希望只重新渲染这个部分,而其它蓝色的节点是我们不希望重复渲染的。那么怎么解决呢?生命周期的shouldComponentUpdate就可以简单解决。
在这里插入图片描述

shouldComponentUpdate介绍

shouldComponentUpdate(nextProps, nextState)

  • nextProps: 表示下一个props。
  • nextState: 表示下一个state的值。

官方API解释道根据 shouldComponentUpdate() 的返回值,判断 React 组件的输出是否受当前 state 或 props 更改的影响。默认行为是 state 每次发生变化组件都会重新渲染。大部分情况下,你应该遵循默认行为。

shouldComponentUpdate(nextProps, nextState){
    //组件是否需要更新,需要返回一个布尔值,返回true则更新,返回flase不更新,这是一个关键点
    console.log('shouldComponentUpdate组件是否应该更新,需要返回布尔值',nextProps, nextState)
    return true
}

当 props 或 state 发生变化时,shouldComponentUpdate() 会在渲染执行之前被调用。返回值默认为 true。首次渲染或使用 forceUpdate() 时不会调用该方法。

使用shouldComponentUpdate性能优化

React中props,state值的变化,会导致组件重新渲染。使用shouldComponentUpdate就是为了减少render不必要的渲染。 返回布尔值,然后做 Virtual DOM 比较,并得出是否需要做真实 DOM 更新,尽管React的虚拟算法复杂度已经有了很多优化,但是在大规模组件更新时,依然会是个不必要的损耗。会带来很多无必要的渲染并成为性能瓶颈。接下来使用来这个生命周期来解决吧

例子:

import React, { Component } from 'react'
class Title extends Component {
    shouldComponentUpdate(nextProps){
        return nextProps.title!==this.props.title
    }
    render() {
        console.log("我是title组件")
        return (
            <div>
                标题:{this.props.title}
            </div>
        )
    }
}

class Count extends Component {
    render() {
        console.log("我是条数组件")
        return (
            <div>
                条数:{this.props.count}
            </div>
        )
    }
}

export default class Purememo extends Component {
    constructor(props){
        super(props)
        this.state={
            title:'shouldComponentUpdate使用',
            count:0
        }
    }
    componentDidMount(){
        setInterval(()=>{
            this.setState({
                count:this.state.count+1
            })
        },1000)
    }
    render() {
        return (
            <div>
                <Title title={this.state.title}></Title>
                <Count count={this.state.count}></Count>
            </div>
        )
    }
}

Purememo整个组件会重新渲染,如果不适用shouldComponentUpdate那么Title,Count会一直渲染,但是使用shouldComponentUpdate后Title则不会发生渲染。

当然你也可以考虑使用内置的 React.PureComponent 组件,shouldComponentUpdate()。PureComponent 会对 props 和 state 进行浅层比较,并减少了跳过必要更新的可能性。不建议shouldComponentUpdate() 中进行深层比较或使用 JSON.stringify()。这样非常影响效率,且会损害性能。

面对复杂的对象时,这样的数据就没有效果了,因为在js中,object,array,function属于引用类型,即使改变其中数据,他们指向的还是同一内存地址,所以采用上面的判断就不行了。例如:

 obj: {
    age: 12,
    name: 'xiaoming',
    student: {
        count: 1
    }
}

解决方法有以下几种:

  1. 使用setState改变数据之前,先采用es6中assgin进行拷贝,但是assgin只深拷贝的数据的第一层,所以说不是最完美的解决办法。
const o2 = Object.assign({},this.state.obj)
    o2.student.count = '00000';
    this.setState({
        obj: o2,
    })

  1. 使用JSON.parse(JSON.stringfy())进行深拷贝,但是遇到数据为undefined和函数时就会错。
const o2 = JSON.parse(JSON.stringify(this.state.obj))
    o2.student.count = '00000';
    this.setState({
        obj: o2,
    })
  1. 使用react官方推荐的第三方库:immutable.js进行项目的搭建。immutable中讲究数据的不可变性,每次对数据进行操作前,都会自动的对数据进行深拷贝,项目中数据采用immutable的方式,可以轻松解决问题,但是又多了一套API去学习。
    在这里插入图片描述
    在这里插入图片描述
    关于immutable.js可参考
    精读 Immutable 结构共享
    深入探究Immutable.js的实现机制(一)
    深入探究Immutable.js的实现机制(二)
    了解Clojure的持久变量

部分参考他人,侵删

发布了82 篇原创文章 · 获赞 46 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/weixin_43720095/article/details/104903588
今日推荐