PureComponent
是和 shouldComponentUpdate
這個生命週期息息相關的react
React
中,當父組件中觸發setState
, 儘管未修改任何 state
中的值也會引發全部子組件的從新渲染, 更況且是修改了某個state
segmentfault
還有, 當父組件傳給子組件的props
發生改變, 無論該props
是否被子組件用到, 都會去從新渲染子組件。瀏覽器
其實咱們也能夠想獲得, setState 會去觸發 render, 因此父組件render
函數中的子組件都會被從新渲染, 所以也就無關state
與props
了
針對這個問題我實現了個例子, 來看一下下面這個例子性能優化
setState但未修改任何state
父組件觸發 setState
方法, 但未更新任何state
dom
import TodoItem from './components/todoItem/todoItem' // 父組件代碼 class TodoList extends Component { noChange() { console.log('觸發setState') this.setState(() => ({ })) } render() { const { todoList } = this.state return ( <div className="wrap"> <button onClick={() => this.noChange()}>沒有變化的setState</button> { todoList.map( (item,index) => <TodoItem key={index} data={item} /> ) } </div> ) } } // 子組件代碼 class TodoItem extends Component { constructor(props) { super(props) } componentWillUpdate() { console.log('我被更新了') } render() { return ( <div> { this.props.data.thing } </div> ) } }
咱們在子組件中預留了componentWillUpdate
方法, 用來監測子組件是否被跟新函數
componentWillUpdate() { console.log('我被更新了') }
實驗結果: 性能
咱們能夠看到, 每一次的點擊都引發了子組件的update
優化
無端的重複update
, 這會致使業務規模擴大後十分的影響性能.this
爲此我監測了一下頁面的重繪事件:spa
綠色區域是瀏覽器發成重繪的地方
能夠看到todoList
其實並無引發瀏覽器的repaint
, 所以能夠推測, 實際dom
並無更新這在渲染頁面前被dom diff
給排除掉了, 所以性能損耗在了轉換成Virtual DOM
的過程當中
shouldComponentUpdate(nextProps, nextState), 默認返回true
shouldComponentUpdate
是 React
中作性能優化的重要手段, 看這個英文翻譯咱們大概也能猜出個一二來 --- '組件是否跟新?'
React
會根據 shouldComponentUpdate
的返回結果來決定該組件是否從新渲染, 若是返回True
就渲染, 若是返回False
就從新渲染
基於這個特性, 咱們來修改一下上面問題中的代碼
// 父組件無變化, 所以省略 // 子組件代碼 class TodoItem extends Component { // ...省略其餘原有的代碼 // --------- 新增代碼 ------------- shouldComponentUpdate(nextProps, nextState) { // 判斷下 當前 props傳入的data.thing 是否和新傳入的 data.thing 相同 return this.props.data.thing !== nextProps.data.thing } // --------- 新增代碼 ------------- }
實驗結果:
咱們能夠看到update
事件確實消失了
看了shouldComponentUpdate
函數的做用, 就可以理解PureComponent
了? 它其實就是在幫咱們作這樣一件事:
自動的幫咱們編寫 shouldComponentUpdate
方法, 避免咱們爲每一個組件都編寫一次的麻煩
咱們只須要這樣, 就能夠一步到位
import React, { PureComponent } from 'react' class TodoItem extends PureComponent { }