React组件更新优化

10 篇文章 0 订阅

优化更新机制

在React默认更新机制中,默认的是只要一个组件的state发生变化,则该组件的所有子组件都会触发更新机制,如下面代码:Root的state只与A与A_1有关,与A_2和B无关

import React, { Component, Fragment } from 'react'

class A extends Component {
    render() {
        console.log('A组件更新了')
        return (
            <Fragment>
                <A_1 data={this.props.data}/>
                <A_2/>
            </Fragment>
        );
    }
}

class A_1 extends Component {
    render() {
        console.log('A_1组件更新了')
        return (
            <div>
                组件A_1
            </div>
        );
    }
}


class A_2 extends Component {
    render() {
        console.log('A_2组件更新了')
        return (
            <div>
                组件A_2
            </div>
        );
    }
}


class B extends Component {
    render() {
        console.log('B组件更新了')
        return (
            <div>
                组件B
            </div>
        );
    }
}


class Root extends Component {
    constructor() {
        super()
        this.state = {
            data: 'xxx'
        }
    }

    eventClick = () => {
        this.setState({
            data: 'xxxx'
        })
    }

    render() {
        return (
            <Fragment>
                <button onClick={this.eventClick}>更改root状态按钮</button>
                <A data={this.state.data}/>
                <B/>
            </Fragment>
        )
    }
}

期望更新的状态是Root和A还有A_1触发更新,A_2和B不触发更新,但是实际上Root下的所有组件都会发生更新,即A_2和B的更新是无用的(绿色是期望render路径,红色是无用render)


PureComponent

PureComponent会自动识别哪些组件状态有更改并且只更新发生变化的组件,使用时只需把继承Component类换成继承PureComponent即可

import React, { PureComponent } from 'react'

class App extends PureComponent {
    
}

此时已经可以把A_2和B的render去掉了

Component和PureComponent区别

继承Component时,只要state有发生改变,,就会触发重新渲染,而不管这个state里的内容是否会和原来一样

import React from 'react';

class App extends React.PureComponent {
    constructor() {
        super()
        this.state ={
            str: 'test'
        }
    }
    
    eventClick = () => {
        this.setState({
            str: 'test'
        })
    }
    
    render() {
        console.log('已更新')	// 点击时,只会打印一次'已更新',如果是继承Component,则点击一次打印一次
        return (
            <div >
                <button onClick={this.eventClick}>test</button>
            </div>
        )
    }
}

但是PureComponent只能进行浅比较,当层级多(对象一级属性的value为引用类型)时则无法比较成功

import React from 'react';

class App extends React.PureComponent {
    constructor() {
        super()
        this.state ={
            obj: {
                num : 1
            }
        }
    }
    
    eventClick = () => {
        this.setState({
            obj: {
                num:1
            }
        })
    }
    
    render() {
        console.log('已更新')	// 无法判断出{num : 1}的内容是不变的,因此此时点击一次会打印一次
        return (
            <div >
                <button onClick={this.eventClick}>test</button>
            </div>
        )
    }
}

因此如果想完全做到渲染性能优化还是应该使用shouldComponentUpdate重写重新渲染逻辑


shouldComponentUpdate

常规写法

shouldComponentUpdate(nextProps, nextState) {
    return nextState.xxx !== this.state.xxx		// 或者nextProps.xxx !== this.props.xxx	
}

这里一般都需要指定到具体的值,因为如果没有设置state默认是null,没有传props默认是{},null和{}的判断相等标准有所区别

if({} !== {}){
    console.log('true')      // 打印
}
if(null !== null) {
    console.log('true')      // 不打印
}

如下面例子,当在App类中设置了渲染更新标准时,即使不用PureComponent,也不会多次执行更新渲染,同时也可以解决更深度的比较

import React from 'react';

class Demo extends React.Component {
    constructor() {
        super()
        this.state ={
            obj:{
                str:'xxx'
            }
        }
    }
    
    shouldComponentUpdate(nextPops, nextState) {
        return nextState.obj.str !== this.state.obj.str		// 如果是 nextState.obj !== this.state.obj 则还是会多次渲染
    }

    eventClick = () => {
        this.setState({
            obj:{
                str:'xxx'
            }
        })
    }
    
    render() {
        console.log('已更新')	
        return (
            <div >
                <button onClick={this.eventClick}>test</button>
            </div>
        )
    }
}

export default Demo
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值