• 6. React.Component 和 React.PureComponent 的区别?


    6. React.Component 和 React.PureComponent 的区别?

    区别

    PureComponent 表示一个纯组件, 可以用来优化 React 程序, 减少 render 函数执行的次数, 从而提高组件的性能。

    React 中, 当 prop 或者 state 发生变化时, 可以通过在 shouldComponentUpdate 生命周期函数中执行 return false 来阻止页面的更新, 从而减少不必要的 render 执行。React.PureComponent 会自动执行 shouldComponentUpdate

    不过, pureComponent 中的 shouldComponentUpdate() 进行的是浅比较, 也就是说如果是引用数据类型的数据, 只会比较不是同一个地址, 而不会比较这个地址里面的数据是否一致。浅比较会忽略属性和或状态突变情况, 其实也就是数据引用指针没有变化, 而数据发生改变的时候 render 是不会执行的。如果需要重新渲染那么就需要重新开辟空间引用数据。PureComponent 一般会用在一些纯展示组件上。

    使用 pureComponent 的好处: 当组件更新时, 如果组件的 props 或者 state 都没有改变, render 函数就不会触发。省去虚拟 DOM 的生成和对比过程, 达到提升性能的目的。这是因为 react 自动做了一层浅比较。

    例子

    使用 Component

    import React, {Component} from "react";
    
    class Foo extends Component {
        render() {
            console.log("foo-render")
            const {num} = this.props;
            return 
    foo-{num}
    ; } } class App extends Component { state = {num: 0,}; handle = () => { this.setState({num: 0,}); }; render() { const {num} = this.state; return (
    ); } }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    点击按钮, 即使 num 值不变, 组件 Foo 仍然更新了, 控制台打印了 foo-render

    使用 PureComponent

    import React, {PureComponent, Component} from "react";
    
    class Foo extends PureComponent {
        render() {
            console.log("foo-render")
            const {num} = this.props;
            return 
    foo-{num}
    ; } }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    只有 num 值改变时, 才会触发 Foo 组件 render

    原理

    react 源码搜索 checkShouldComponentUpdate 方法可以看到下面代码, 去掉 dev 内容。

    /**
     * 是否更新组件
     * @param {*} workInProgress
     * @param {*} ctor
     * @param {*} oldProps
     * @param {*} newProps
     * @param {*} oldState
     * @param {*} newState
     * @param {*} nextContext
     * @returns true 更新 false 不更新
     **/
    function checkShouldComponentUpdate(workInProgress, ctor, oldProps, newProps, oldState, newState, nextContext) {
        const instance = workInProgress.stateNode;
        // 组件实例上有shouldComponentUpdate方法, 调用拿方法返回值  
        if (typeof instance.shouldComponentUpdate === 'function') {
            let shouldUpdate = instance.shouldComponentUpdate(newProps, newState, nextContext,);
            return shouldUpdate;
        }
        // 重点在这  
        // 原型上有isPureReactComponent属性, 则是extends PureComponent  
        // PureComponent在react源码中声明时, 在原型上添加了 isPureReactComponent 属性  
        PureComponent.prototype.isPureReactComponent === true
        if (ctor.prototype && ctor.prototype.isPureReactComponent) {
            return (
                // 只对props和state浅比较      
                !shallowEqual(oldProps, newProps) || !shallowEqual(oldState, newState));
        }
        return true;
    }
    
    • 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

    下面代码是 isPureReactComponent 来源, 是 react 在声明 PureComponent 时, 在原型上添加了 isPureReactComponent = true 的属性。

    function ComponentDummy() {
    }
    
    ComponentDummy.prototype = Component.prototype;
    
    function PureComponent(props, context, updater) {
        this.props = props;
        this.context = context;
        // If a component has string refs, we will assign a different object later. 
        this.refs = emptyObject;
        this.updater = updater || ReactNoopUpdateQueue;
    }
    
    const pureComponentPrototype = (PureComponent.prototype = new ComponentDummy());
    pureComponentPrototype.constructor = PureComponent;
    // Avoid an extra prototype jump for these methods.
    Object.assign(pureComponentPrototype, Component.prototype);
    // PureComponent 原型上有个 isPureReactComponent 属性, 用来标识是 PureComponent 组件 
    pureComponentPrototype.isPureReactComponent = true;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    所以 if (ctor.prototype && ctor.prototype.isPureReactComponent) {} 判断是 PureComponent 组件, 才走浅比较逻辑。

  • 相关阅读:
    删除A文件夹中 AB文件夹共有的文件
    uniapp Map 计算实时定位到达某个具体位置距离 及 在uniappMap上绘制浮框
    怎么把PDF转Word?这个攻略请收藏好
    使用python读写xlsx格式中的数据【xlrd、pywin32】
    头文件和编译的问题
    k8s之service五种负载均衡byte的区别
    lv8 嵌入式开发-网络编程开发 01什么是互联网
    把握效率与最优性:Dijkstra算法的探索
    2022买护眼灯到底有没有用?双十二学生护眼灯该怎么选择
    【ESP 保姆级教程】疯狂点灯篇 —— 案例:ESP8266 + 风扇 + 按键(模拟按键控制电器设备开关)
  • 原文地址:https://blog.csdn.net/m0_51180924/article/details/126554179