在優化 React 組件的時候咱們經常會看到 Pure Component 的說法,所謂 Pure Component 就是在 props,state 和 context 不變的狀況下,組件的 render 結果也是不變的。基於這個前提,咱們能夠很方便地用 shouldCompoentUpdate 來優化組件,減小 render。react
import React, { Component } from 'react'; import shallowequal from 'shallowequal'; class FullName extends Component { shouldComponentUpdate(nextProps) { return !shallowequal(this.props, nextProps) } render() { const { firstName, lastName } = this.props; return ( <div>{firstName} {lastName}</div> ) } }
React 官方也提供了 PureRenderMixin (給 React.createClass 用)和 React.PureComponent 來讓咱們方便地聲明一個 Pure Component。git
那麼既然有 Pure Component 的說法,確定還有相對的 Impure Component。一言以蔽之,只要你的組件依賴了 props 和 state (context 比較特殊,後面會講到)以外的數據,你的組件就不是 pure 的,咱們來看例子。github
class FullName extends Component { render() { const { firstName, lastName } = this.props; return ( <div>{firstName} {lastName} - {new Date}</div> ) } }
咱們在這裏增長了一個當前日期的顯示,致使即便 firstName 和 lastName 不變化,組件每次 render 的結果也是不一樣的,這個組件就沒辦法用 shouldCompoentUpdate 去優化了。閉包
class App extends Component { state = { lastName: '', } handleChange = e => { this.setState({ lastName: e.target.value }); } renderLastName = () => { return this.state.lastName; } render() { <div> <input type="text" onChange={this.handleChange} /> <FullName firstName="Ava" lastName={this.renderLastName} /> </div> } } class FullName extends Component { render() { const { firstName, lastName } = this.props; return ( <div>{firstName} {lastName()}</div> ) } }
這個例子咱們把 lastName 變成一個方法傳進來,這樣其實 FullName 組件經過閉包,而不是經過 props,依賴了 App 的 state.lastName ,致使在 firstName 和 lastName 都不變化的狀況下,FullName 會根據 state.lastName 的不一樣 render 出不一樣的結果。優化
class App extends Component { static childContextTypes = { firstName: React.PropTypes.string, lastName: React.PropTypes.string, } getChildContext() { return { firstName: 'Taylor', lastName: 'Swift', }; } render() { <Segment> <FullName /> </Segment> } } class Segment extends Component { render() { <div>{this.props.children}</div> } } class FullName extends Component { static contextTypes = { firstName: React.PropTypes.string, lastName: React.PropTypes.string, }; render() { const { firstName, lastName } = this.context; return ( <div>{firstName} {lastName}</div> ) } }
這個例子其實算是 React 留給咱們的一個坑,這裏 FullName 是 Pure Component,可是 Segament 卻不是,由於 Segament 的 render 結果間接地依賴了上層的 context。this