React知识整理-性能优化之pureComponent和memo
冰洋 1/12/2020 React
react从入门到放弃
# React.PureComponent
- React.PureComponent 与 React.Component 很相似。两者的区别在于 React.Component 并未实现 shouldComponentUpdate(),而 React.PureComponent 中以浅层对比 prop 和 state 的方式来实现了该函数。
- 如果赋予 React 组件相同的 props 和 state,render() 函数会渲染相同的内容,那么在某些情况下使用 React.PureComponent 可提高性能。
注意:React.PureComponent中的 shouldComponentUpdate()仅对对象浅拷贝做比较。如果对象包含复杂的数据结构,可能无法检查出深层的差别,产生错误的对比。
仅仅在props和state较为简单是使用,或者深层数据结构发生变化调用forceUpdate()
确保组件被正确更新。也可以考虑 immutable对象 (opens new window)加速嵌套数据的比较。
简单实现
// PureComponent.js
import React, { Component } from 'react'
export default class PureComponent extends Component {
isPureComponent = true
//传入新的属性对象和状态对象,然后返回一个是否需要更新的boolean值
shouldComponentUpdate(nextProps,nextState){
// 判断 只要有一个不相等性返回true更新。否则false不更新
return !shallowEqual(this.props,nextProps)||!shallowEqual(this.state,nextState);
}
}
// 浅比较 性格高
// 比较obj1和obj2是否相等,如果相等的话则返回true,不相等返回false,只比较第一层
function shallowEqual(obj1,obj2){
if(obj1 === obj2){
return true;
}
if(typeof obj1 !='object' || obj1 === null ||typeof obj2 !='object' || obj2 === null){
return false;
}
let keys1 = Object.keys(obj1);
let keys2 = Object.keys(obj2);
if(keys1.length != keys2.length){
return false;
}
for(let key of keys1){
if(!obj2.hasOwnProperty(key) || obj1[key]!=obj2[key]){
return false;
}
/* if(obj2.hasOwnProperty(key)){
if(obj1[key] != obj2[key]){
if(typeof obj1[key] == 'object' && typeof obj2[key] == 'object'){
return shallowEqual(obj1[key],obj2[key]);
}
}
}else{
return false;
} */
}
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
30
31
32
33
34
35
36
37
38
39
40
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
30
31
32
33
34
35
36
37
38
39
40
# React.memo
const MyComponent = React.memo(function MyComponent(props) {
/* 使用 props 渲染 */
});
1
2
3
2
3
React.memo为高阶组件。它与 React.PureComponent 非常相似,但它适用于函数组件,但不适用于 class 组件。
如果你的函数组件在给定相同 props 的情况下渲染相同的结果,那么你可以通过将其包装在 React.memo 中调用,以此通过记忆组件渲染结果的方式来提高组件的性能表现。这意味着在这种情况下,React 将跳过渲染组件的操作并直接复用最近一次渲染的结果。
- 浅比较:默认情况下其只会对复杂对象做浅层对比,如果你想要控制对比过程,那么请将自定义的比较函数通过第二个参数传入来实现
function MyComponent(props) { /* 使用 props 渲染 */ } function areEqual(prevProps, nextProps) { /* 如果把 nextProps 传入 render 方法的返回结果与 将 prevProps 传入 render 方法的返回结果一致则返回 true, 否则返回 false */ } export default React.memo(MyComponent, areEqual);
1
2
3
4
5
6
7
8
9
10
11 - 此方法仅作为性能优化 (opens new window)的方式而存在。但请不要依赖它来“阻止”渲染,因为这会产生 bug。
简单实现:
function memo(FuncComponent,fn){
shouldComponentUpdate(nextProps,nextState){
return fn?fn():true
}
return class extends PureComponent{
render(){
return <FuncComponent {...this.props}/>
}
}
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10