react之组件的shouldcomponentUpdate使用&&Component与PureComponent
1). Component存在的问题?
a. 父组件重新render(), 当前组件也会重新执行render(), 即使没有任何变化
b. 当前组件setState(), 重新执行render(), 即使state没有任何变化
测试代码如下,首先是a情况
/**父组件 */ import React, { Component } from 'react' import Child from './Child' class Parent extends Component { state = { money:100 } changeFn = () => { this.setState(state=>({ money:state.money+1 })) } render() { console.log('parent render') return ( <> <h2>parent组件:{this.state.money}</h2> <button onClick={this.changeFn}>Parent测试</button> <Child></Child> </> ); } } export default Parent;
/**子组件 */
import React, { Component } from 'react'
class Child extends Component {
state = {
money:100
}
changeFn = () => {
this.setState(state=>({
money:state.money+1
}))
}
render() {
console.log('child render')
return (
<>
<h2>child组件:{this.state.money}</h2>
<button onClick={this.changeFn}>Child测试</button>
</>
);
}
}
export default Child;
此时修改父组件
如果父组件传入子组件状态,状态更新,两者都更新,这符合正常逻辑,如下所示。但上述的两者并不存在状态继承
b情况测试如下:
此时state并没有更新,但还是触发了render。
这里的问题便涉及到react生命周期相关,钩子图如下
局部放大我们查看下
这里shouldcomponentUpdate默认值为true,所以会往下执行更新流程。如下所示
b. 办法1: 重写shouldComponentUpdate(), 判断如果数据有变化返回true, 否则返回false c. 办法2: 使用PureComponent代替Component d. 说明: 一般都使用PureComponent来优化组件性能
重写方案进行优化完整如下
此时测试如下,子组件点击时不再render
但是目前为止state都是基本数据类型,如果较为复杂时则该方案较难比较,需要自行进行依次对比----浅比较.
2). 解决Component存在的问题
a. 原因: 组件的shouldcomponentUpdate()默认返回true, 即使数据没有变化render()都会重新执行
b. 办法1: 重写shouldComponentUpdate(), 判断如果数据有变化返回true, 否则返回false
c. 办法2: 使用PureComponent代替Component
d. 说明: 一般都使用PureComponent来优化组件性能
3). PureComponent的基本原理
如下所示
此时便解决了以上问题
a. 重写实现shouldComponentUpdate()
b. 对组件的新/旧state和props中的数据进行浅比较, 如果都没有变化, 返回false, 否则返回true
c. 一旦componentShouldUpdate()返回false不再执行用于更新的render()
这里可以结合项目角色授权组件进行测试。
测试发现没有更新子组件,关闭时父组件render,子组件也会触发render。修改如下
4). 面试题:
组件的哪个生命周期勾子能实现组件优化?
PureComponent的原理?
区别Component与PureComponent?
5)PureComponent使用注意:
如果组件内部的state为对象或数组格式,当该对象或数组内部发生改动时,不能直接获取setState,这里必须使用解构赋值,将对象或数组内部展开,再重新赋值,才会改动
1、该写法无效,不会触发更新
2、解构赋值展开内部才会触发更新
所以为了避免不必要问题,尽量多用解构赋值写法。
***
PureComponent使用注意事项:
即如果改变的是数组或对象内部的某个状态,则必须使用解构赋值语法重新setState,否则不会更新
***.
.