PureComponent
和Component
都是React中的组件类,但它们在实现细节和使用上有些差别。
Component
是React中定义组件的基类,它的shouldComponentUpdate
方法默认返回true,也就是说,每次调用setState
或forceUpdate
方法都会引发组件重新渲染。如果我们希望在一些情况下避免不必要的渲染(例如props
或state
没有变化),就需要在继承自Component
的组件中手动实现shouldComponentUpdate
方法来进行比较。
PureComponent
则提供了一种基于浅比较的优化机制,它默认实现了shouldComponentUpdate
方法,会自动对组件的props
和state
进行浅比较,如果发现props
或state
没有发生变化,则阻止组件的重新渲染,提高性能。对于复杂的数据结构,需要注意进行引用类型的比较,避免误判。
底层处理机制
PureComponent
与Component
的区别在于对shouldComponentUpdate
方法的处理。在React内部实现中,当调用setState
或forceUpdate
方法时,会触发更新过程,有以下几个步骤:
1.修改组件的state和props;
2.调用组件的shouldComponentUpdate方法,决定是否需要重新渲染组件;
3.如果需要重新渲染组件,React会根据虚拟DOM的增量更新算法计算出需要更新的节点,并将变化应用到DOM上。
因此,PureComponent
与Component
的区别在于第2步的处理机制。对于PureComponent
,会在默认实现的shouldComponentUpdate
方法中自动进行浅比较props
和state
,从而判断是否需要重新渲染组件;而对于Component,则需要手动实现shouldComponentUpdate
方法来进行比较。
需要注意的是,虽然PureComponent
的默认实现可以避免一些不必要的渲染,但它并不是完全自动化的,也不能保证在所有情况下都能正确地避免不必要的渲染。在实际应用中,还需要根据具体情况来选择合适的组件类来达到最佳的性能和开发效率。
理解浅比较
function isObject(obj) {return obj !== null && typeof obj === 'object';
}function shallowEqual(objA, objB) {if (Object.is(objA, objB)) {return true;}if (!isObject(objA) || !isObject(objB)) {return false;}const keysA = Reflect.ownKeys(objA);const keysB = Reflect.ownKeys(objB);if (keysA.length !== keysB.length) {return false;}for (let i = 0; i < keysA.length; i++) {const key = keysA[i];if (!objB.hasOwnProperty(key) || !Object.is(objA[key], objB[key])) {return false;}}return true;
}
注意
1.这里为什么用Object.is,因为我们这里认为nan等于nan,所以我们要用 这个方法!
2.如果我们的浅比较无法导致更新,那么我们可以通过this. forceUpdate(); //跳过默认加的shouldComponentUpdate, 直接更新
如果使用Component但是没有自己实现shouldComponentUpdate怎么办?
如果没有自己实现shouldComponentUpdate
方法,Component会默认返回true
,也就是每次调用setState
或者forceUpdate
都会导致组件的重新渲染,甚至在组件的props
或state
没有变化时也会重新渲染。
这在一些情况下可能会导致性能问题,因此我们可以通过以下两种方式来优化组件的性能:
手动实现shouldComponentUpdate
方法,对组件的属性进行比较,避免不必要的重新渲染。例如,在props
或者state
没有变化时,返回false
,否则返回true
。在比较属性时,我们可以使用浅比较或者深比较来实现,具体方法取决于属性的数据类型和结构。一般来说,如果属性比较简单,我们可以使用浅比较,否则可以使用第二种方式。
使用React.memo
高阶组件对组件进行包装,将组件包装成具有浅比较优化功能的组件。React.memo
的作用是对组件的props
进行浅比较,如果props
没有变化,则不会重新渲染组件。使用React.memo
的方式非常简单,只需要将组件作为React.memo
的参数传入即可,例如:
import React, { memo } from 'react';const MyComponent = ({ name, age }) => {return (<div><span>Name: {name}</span><span>Age: {age}</span></div>);
};export default memo(MyComponent);