React性能优化
2020-12-24 本文已影响0人
肾仔博
1、keys的优化
1.key应该要唯一;
2.key不要使用随机数;
3.使用index作为key,对性能并没有优化;
<ul>
{
this.state.movies.map((item, index) => {
return <li key={item}>{item}</li>
})
}
</ul>
2、shouldComponentUpdate
React提供了一个生命周期方法shouldComponentUpdate(),这个方法能够控制render方法的调用,它接收参数,并且需要有返回值。
- 该方法有两个参数:
nextProps:修改后,最新的props属性;
nextState:修改后,最新的state属性; - 该方法返回值是一个boolean类型
返回值为:true,则需要调用render方法;
返回值为:false,则不需要调用render方法;
默认值返回的是true,只要state发生改变,则会调用render方法;
shouldComponentUpdate(nextProps, nextState) {
if (this.state.counter !== nextState.counter) {
return true;
}
return false;
}
3、PureComponent
PureComponent就是检测类组件中的state和props是否有发生变化,若发生改变则决定重新渲染组件。
用法:class App extends PureComponent{}
(使用类组件都最好用PureComponent包裹)
- PureComponent在shouldeComponentUpdate里,下面的代码就是shouldComponentUpdate的一部分源码
if (ctor.prototype && ctor.proptype.isPureReactComponent){
return (
!shallowEqual(oldProps,newProps) ||
!shallowEqual(oldState,newState)
);
}
shallowEqual这个方法就是进行一个浅层比较;
- 什么是浅层比较????
在js中的===是做浅层比较,它会检查两边的数值是否为同一个对象的引用,若相同则为true,否则为false;
- JavaScript中的==和===的区别
因为JS是弱类型语言,如果两个数值用==进行比较的话,==操作符会自动将0,' '(空字符串),null,undefined转为布尔类型;
因此代码会出现:
0 == ' ' //true
null == undefined //true
[1] == true //true
所以JS提供了全等操作符===,它要求===两边的类型和数值都必须一样,这才能返回true,但是它疏忽了两种情况:
+0 === -0 //true,但我们期待它返回false
NaN === NaN //false,但我们期待它返回true
- 这个时候就需要用Object.is()方法
function (x,y) {
if(x === y){
//处理+0===-0的情况
return x !== 0 || 1/x === 1/y;
}else{
//处理NaN===NaN的情况
return x !== x && y !== y;
}
}
Object.is()方法
解析shallowEqual的代码:
// 用原型链的方法
const hasOwn = Object.prototype.hasOwnProperty
// 这个函数实际上是Object.is()的polyfill
function is(x, y) {
if (x === y) {
return x !== 0 || y !== 0 || 1 / x === 1 / y
} else {
return x !== x && y !== y
}
}
export default function shallowEqual(objA, objB) {
// 首先对基本数据类型的比较
if (is(objA, objB)) return true
// 由于Obejct.is()可以对基本数据类型做一个精确的比较, 所以如果不等
// 只有一种情况是误判的,那就是object,所以在判断两个对象都不是object
// 之后,就可以返回false了
if (typeof objA !== 'object' || objA === null ||
typeof objB !== 'object' || objB === null) {
return false
}
// 过滤掉基本数据类型之后,就是对对象的比较了
// 首先拿出key值,对key的长度进行对比
const keysA = Object.keys(objA)
const keysB = Object.keys(objB)
// 长度不等直接返回false
if (keysA.length !== keysB.length) return false
// key相等的情况下,在去循环比较
for (let i = 0; i < keysA.length; i++) {
// key值相等的时候
// 借用原型链上真正的 hasOwnProperty 方法,判断ObjB里面是否有A的key的key值
// 属性的顺序不影响结果也就是{name:'daisy', age:'24'} 跟{age:'24',name:'daisy' }是一样的
// 最后,对对象的value进行一个基本数据类型的比较,返回结果
if (!hasOwn.call(objB, keysA[i]) ||
!is(objA[keysA[i]], objB[keysA[i]])) {
return false
}
}
return true
}
- 注意:shallowEqual中的浅层比较仅用了Object.is()方法对数据进行了基本数据的比较,若数据是对象的话,可能会出现不符合预期的情况,因此浅层比较不适用于嵌套类型的比较!!
4、memo(高阶组件)
memo()能让函数式组件提升性能
const MemoText = memo(function fn(){
})