组件更新机制
三种组件更新的情况:
- 调用 forceUpdate 方法强制更新
- 调用 setState 方法更新数据
- props 值发生变化时
问题:当组件进行嵌套时,更新了其中的某一个组件后,其他组件的更新方式?
当一个组件进行更新时,不但会更新自己,也会更新后代组件。但是不会更新父组件和兄弟组件
减轻 state
目标: 降低页面更新的频率 (只要state中数据发生改变,页面就会重载)
方式: 不用做渲染的数据,不要放在state中 (例如:定时器,直接挂在到this上即可)
class App extends React.Component {
// state中只保存要渲染到页面上的数据
state = {
userInfo: {
username: 'zs',
roleName: '超级管理员'
},
goodsList: [
{
id: 1, goodsName: '键盘', goodsPrice: 399},
{
id: 2, goodsName: '鼠标', goodsPrice: 199},
{
id: 3, goodsName: '耳机', goodsPrice: 699},
]
}
// 不用渲染到页面上的数据就直接挂在到 this 上即可
componentDidMount () {
this.timerId = setInterval(() => {
}, 800)
}
componentWillUnmout () {
clearInterval(this.timerId)
}
}
避免不必要的渲染
组件更新机制: 当一个组件进行更新时,不但会更新自己,也会更新后代组件。但是不会更新父组件和兄弟组件
存在的问题: 子组件没有变化,但是因为父组件发生了更新,所以子组件也要进行更新。这种更新是没有必要的,只会浪费系统性能
解决方案: 钩子函数 shouldComponentUpdate 用来判断组件是否需要更新
执行机制: 在执行 render 渲染页面前会先调用 shouldComponentUpdate 来判断是否需要进行渲染,如果返回值为true则进行渲染,反之则不渲染 (shouldComponentUpdate --> render)
class App extends React.Component {
// 参数1: 下一次 props 的值
// 参数2: 下一次 state 的值
// 返回值: 返回true则更新,返回false则不更新
shouldComponentUpdate(nextProps,nextState){
return true/false
}
render () {
...}
}
state
在 shouldComponentUpdate 方法中可以使用两个数据
- nextState: state更新后的值
- this.state: 未更新之前的值
- 判断更新后的值和跟新前的值是否发生变化即可
import React from 'react'
import ReactDOM from 'react-dom'
// 目标: state 控制更新
// 每次点击按钮更新num中的数字
// 核心思想: 判断更新前后state中的num值是否相同,相同则不更新组件,不相同则更新
class App extends React.Component {
state = {
count: 0
}
shouldComponentUpdate (nextProps, nextState) {
console.log('nextState', nextState)
console.log('this.state', this.state)
// 判断更新后的state和更新前的state数据是否一致
// 不一致返回true执行更新,一致返回false不更新
return nextState.count !== this.state.count
}
updateApp = () => {
this.setState({
count: Math.floor(Math.random() * 3)
})
}
render () {
console.log('render')
return (
<div>
<p>{
this.state.count}</p>
<button onClick={
this.updateApp}>更新组件</button>
</div>
)
}
componentDidUpdate () {
console.log('App-componentDidUpdate')
}
}
ReactDOM.render(<App />, document.querySelector('#app'))
props
shouldComponentUpdate 方法中的另外两个数据
- nextProps: props 更新后的值
- this.props: props 未更新前的值
- 判断两次props中的值,来决定是否要更新
- 注意: 当子组件不渲染时,父组件也不要进行渲染
import React from 'react'
import ReactDOM from 'react-dom'
class App extends React.Component {
state = {
count: 0
}
// 判断父组件是否需要更新
shouldComponentUpdate (nextProps, nextState) {
return nextState.count !== this.state.count
}
updateApp = () => {
this.setState({
count: Math.floor(Math.random() * 3)
})
}
render () {
return (
<div>
<Show num={
this.state.count} />
<button onClick={
this.updateApp}>更新组件</button>
</div>
)
}
componentDidUpdate () {
console.log('App-componentDidUpdate')
}
}
class Show extends React.Component {
// 判断子组件是否需要更新
shouldComponentUpdate (nextProps) {
console.log('nextProps', nextProps)
console.log('this.props', this.props)
return nextProps.num !== this.props.num
}
render () {
return (
<div>{
this.props.num}</div>
)
}
componentDidUpdate () {
console.log('Show-componentDidUpdate')
}
}
ReactDOM.render(<App />, document.querySelector('#app'))
纯组件
纯组件: React.PureComponet 与 React.Component 功能相似,也可以用来实现类组件
作用: 纯组件内部自动实现了 shouldComponentUpdate 钩子函数
原理: 纯组件内部会自动比对前后两次 props 和 state 的值来决定是否需要重新渲染
class App extends React.PureComponent {
render () {
return (
<div>纯组件</div>
)
}
}
案例:使用纯组件完成随机数案例
import React from 'react'
import ReactDOM from 'react-dom'
class App extends React.PureComponent {
state = {
count: 0
}
updateApp = () => {
this.setState({
count: Math.floor(Math.random() * 3)
})
}
render () {
return (
<div>
<div>{
this.state.count}</div>
<div><button onClick={
this.updateApp}>随机更新</button></div>
</div>
)
}
componentDidUpdate () {
console.log('App-componentDidUpdate')
}
}
ReactDOM.render(<App />, document.querySelector('#app'))