React.Component
和React.PureComponent
很類似,兩則的區別在於,PureComponent
類幫咱們以淺比較的方式對比props
和state
,實現了shouldComponentUpdate()
函數,在某些狀況下,使用PureComponent
能夠減小render
函數的執行,提高性能。react
當Index組件繼承Component
類算法
初次渲染時控制檯會依次打印"constructor
"、"render
";bash
當第一次點擊按鈕更新state
時,控制檯會依次打印"render
"、"componentDidUpdate
";函數
後續每次觸發點擊事件,儘管flag的值沒有變化,控制檯仍是會依次打印"render
"、"componentDidUpdate
",說明組件依然調用render()
、componentDidUpdate()
函數,顯然這是多餘的,一般咱們會手動從新實現shouldComponentUpdate(nextProps, nextState)
函數判斷state
、props
的狀態再來決定是否須要從新渲染性能
import React from 'react';
class Index extends React.PureComponent{
constructor(props) {
super(props);
this.state = {
flag:false
};
console.log('constructor');
}
changeState = () => {
this.setState({
flag: true
})
};
render() {
console.log('render');
return (
<div>
<button onClick={this.changeState}>Click me</button>
<div>
{this.state.flag.toString()}
</div>
</div>
);
}
componentDidUpdate() {
console.log("componentDidUpdate")
}
}
export default Index;
複製代碼
當Index組件繼承PureComponent
類ui
初次渲染和第一次點擊按鈕更新state
時控制檯輸出同上面繼承Component
同樣沒有變化this
後續每次觸發點擊事件,控制檯無輸出, 省去執行render
函數生成虛擬DOM,進行DIFF算法比較等後續操做spa
if (this._compositeType === CompositeTypes.PureClass) {
shouldUpdate = !shallowEqual(prevProps, nextProps) || !shallowEqual(inst.state, nextState);
}
複製代碼
PureComponent
默認實現的shouldComponentUpdate()
方法使用的是淺比較: 即值的比較或引用的比較, 不會進行深層次的對比,因此當props
或state
的值是引用類型時,即便對象的值改變了,可是對象的引用沒變code
import React from 'react';
class IndexPage extends React.PureComponent{
constructor(props) {
super(props);
this.state = {
arr: [1,2,3,4,5]
};
}
changeArr = () => {
let {arr} = this.state
arr.pop()
this.setState({
arr
})
console.log("changeArr", arr)
};
render() {
const { arr } = this.state
console.log('render', arr);
return (
<div>
<button onClick={this.changeArr}>pop</button>
<ul>
{
arr.map(item => <li key={item}>{item}</li>)
}
</ul>
</div>
);
}
componentDidUpdate() {
console.log("componentDidUpdate")
}
}
export default IndexPage;
複製代碼
render (5) [1, 2, 3, 4, 5]
changeArr (4) [1, 2, 3, 4]
, changeArr (4) [1, 2, 3]
......
可是render
函數不執行, 由於PureComponent
實現的shouldComponentUpdate()
認爲值的引用沒有變,故不執行後續的操做,只有在引用改變的狀況下函數纔會返回true
下面例子中的render
函數只會在剛建立的時候執行一次, 後續的點擊按鈕操做,因爲PureComponent
中的ShouldComponentUpdate()
執行淺比較(對象值的引用沒變),不會觸發render
函數的執行,其子組件也不會更新。component
import React from 'react';
import Item from './Item'
class IndexPage extends React.PureComponent{
constructor(props) {
super(props);
this.state = {
arr: [1,2,3,4,5]
};
}
changeArr = () => {
let {arr} = this.state
arr.pop()
this.setState({
arr
})
console.log("changeArr", arr)
};
render() {
const { arr } = this.state
console.log('render', arr);
return (
<div>
<button onClick={this.changeArr}>pop</button>
<ul>
<Item arr={arr} />
</ul>
</div>
);
}
componentDidUpdate() {
console.log("componentDidUpdate")
}
}
export default IndexPage;
複製代碼
// Item.js
import React, { Fragment, Component } from 'react'
class Index extends Component {
render() {
const { arr } = this.props;
console.log("children", arr)
return (
<Fragment>
{
arr.map(item => <li key={item}>{item}</li>)
}
</Fragment>
)
}
}
export default Index;
複製代碼
PureComponent
已經用淺層對比props
、state
的方式替咱們實現了shouldComponentUpdate()
, 不只能影響自身,還會影響其子組件;PureComponent
某些狀況下(props
或state
的值不常常變更, 由於淺比較也會耗時)能夠提高性能;Component
中的組件shouldComponentUpdate()
默認狀況下老是返回true;