React.Component
是使用 ES6 classes 方式定义 React 组件的基类:
class Greeting extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
- PureComponent 和 memo 仅作为性能优化的方式而存在。
- 但请不要依赖它来“阻止”渲染,因为这会产生 bug。
- PureComponnet 和 memo 都是通过对 props 值的浅比较来决定该组件是否需要更新的。
PureComponent (类组件)
React.PureComponent
与React.Component
很相似。- 两者的区别在于
React.Component
并未实现shouldComponentUpdate()
, - 而
React.PureComponent
中以浅层对比 prop 和 state 的方式来实现了该函数。
如果赋予 React 组件相同的 props 和 state,render() 函数会渲染相同的内容,那么在某些情况下使用 React.PureComponent
可提高性能。
memo(函数式组件)
React.memo
为高阶组件。它与React.PureComponent
非常相似,但只适用于函数组件,而不适用 class 组件。
const MyComponent = function MyComponent(props) {
/* 使用 props 渲染 */
};
export default React.memo(MyComponent)
如果你的函数组件在给定相同 props 的情况下渲染相同的结果,那么你可以通过将其包装在 React.memo
中调用,以此通过记忆组件渲染结果的方式来提高组件的性能表现。这意味着在这种情况下,React 将跳过渲染组件的操作并直接复用最近一次渲染的结果。
React.memo
仅检查 props
变更。如果函数组件被 React.memo
包裹,且其实现中拥有 useState 或 useContext
的 Hook,当 context
发生变化时,它仍会重新渲染。
- 默认情况下其只会对复杂对象做浅层对比,如果你想要控制对比过程,那么请将自定义的比较函数通过第二个参数传入来实现。
function MyComponent(props) {
/* 使用 props 渲染 */
}
function areEqual(prevProps, nextProps) {
/*
如果把 nextProps 传入 render 方法的返回结果与
将 prevProps 传入 render 方法的返回结果一致则返回 true,
否则返回 false
*/
}
export default React.memo(MyComponent, areEqual);
示例:
- 无memo示例:
// 子组件代码:
import React, { memo } from 'react';
const Child = ()=>{
console.log("2. 子组件渲染了")
return (<div>子组件</div>)
}
export default Child
// 父组件代码:
import React, { memo } from 'react';
import Child from './Child.jsx'
const Father = ()=>{
const [name,setName]=React.useState('');
console.log("1. 父组件渲染了")
return (<div>
/* 在input框中输入内容,会走setName导致App组件重新渲染,但是子组件Child也会进行渲染。 */
父组件:<input type="text" value={name} onChange={ev=>setName(ev.target.value)} />
<Child />
</div>)
}
打印结果:
- 有memo示例:
// 子组件代码:
import React, { memo } from 'react';
const Child = ()=>{
console.log("2. 子组件渲染了")
return (<div>子组件</div>)
}
export default memo(Child)
// 父组件代码:
import React, { memo } from 'react';
import Child from './Child.jsx'
const Father = ()=>{
const [name,setName]=React.useState('');
console.log("1. 父组件渲染了")
return (<div>
/* 解决:子组件使用memo包起来 */
父组件:<input type="text" value={name} onChange={ev=>setName(ev.target.value)} />
<Child />
</div>)
}
打印结果: