簡單的說一下如何在 react 開發中,進行 benchmark,而且會簡單的說一些能夠提高性能的小技巧。html
既然想要進行 benchmark,那麼就須要一個指標來衡量。react 官方已經提供了這樣的工具供開發人員使用。react
官方的文檔能夠參考這裏Performance Tools,在這裏我再作個簡單的介紹。git
import Perf from 'react-addons-perf';
就能夠將Performance Tool
引入到當前的 react app 中使用了。github
Performance Tool
的使用十分方便,在上一步引入的 Perf
自己是個對象,能夠直接調用其方法,來進行性能測試。app
如下這些方法,若是不傳入參數的話,都會調用Perf.getLastMeasurements()
方法,獲取最新的 measurementsdom
componentWillMount
和componentDidMount
的執行時間Wasted
的是指頁面中的 dom 實際並無發生變化,可是組件仍然被渲染的操做,printWasted
就是輸出這些無心義
操做所用的時間
舉個簡單的例子,假設咱們須要渲染一個並無交互的組件,例如一句話,那麼這個組件其實也不存在 lifecycle
,那麼能夠直接使用函數式的方法輸出這個組件函數
我作了個簡單的 demo,能夠 clone 下來本身看下工具
// 使用 component class Text extends React.Component { render () { return ( <div>{ this.props.text }</div> ) } } export default Text // 使用匿名函數 export default (text) => { return ( <div>{ text }</div> ) }
看下 Performance Tool
輸出的結果性能
能夠明顯的看到Benchmark > FunctionWrap
的總時間要小於Benchmark > ComponentWrap
和Benchmark > PureComponentWrap
所用的時間測試
這是由於使用匿名函數,省掉了 lifecycle
的一系列函數調用的時間,Benchmark > PureCompnent
耗時最長是由於React.PureComponent
會在shouldComponentUpdate
中默認進行shallowEqual
的操做,因此初始化渲染會比較慢。
React.PureComponent
和React.Component
的區別就在於PureComponent
會默認帶一個shouldComponentUpdate
的方法,經過shallowEqual
對比當前的 component
是否須要進行從新渲染。
有了這樣的一個簡單的判斷,在不手動寫shouldComponentUpdate
方法時,也能夠得到必定的性能提高。
具體的測試,一樣能夠看這個demo,裏面有相關的測試。
一般在可交互的組件上,咱們會綁定一些事件,例以下面的例子
class User extends React.Component { render () { console.log('render user') return ( <div className='user'> <p>is a component</p> <p>name: { this.props.data.name }</p> <p>id: { this.props.data.id }</p> <div className='buttons'> <button onClick={ this.props.onClick }>Change Data</button> </div> </div> ) } } class PureUser extends React.PureComponent { render () { console.log('render pure user') return ( <div className='user'> <p>is a pure component</p> <p>name: { this.props.data.name }</p> <p>id: { this.props.data.id }</p> <div className='buttons'> <button onClick={ this.props.onClick }>Change Data</button> </div> </div> ) } } class Anonymous extends React.Component { constructor (props) { super(props) this.state = { data: Foo } } render () { return ( <div> <div className='wrap'> { this.renderUser() } { this.renderPureUser() } </div> </div> ) } changeData () { Pref.start() this.setState({ data: Foo }) } renderUser () { return <User data={ this.state.data } onClick={ this.changeData.bind(this) } /> } renderPureUser () { return <PureUser data={ this.state.data } onClick={ this.changeData.bind(this) } /> } }
在這個例子中<Anonymous />
會將state.data
傳遞給自組件,同時會傳遞一個 onClick
的事件回調給子組件。
在運行這個例子時,咱們會發現即便咱們使用React.PureComponent
,而且並無實際改變 state.data
的值,可是 <PureUser />
這個組件仍是會跟<User />
組件同樣,會重複被渲染。
究其緣由,在於onClick
這裏使用了.bind
方法,將changeData
綁定到了當前的做用域內,可是.bind
方法返回的是個匿名函數,因此事實上每次傳入到子組件內的props
都是不一樣的,PureComponent
也會被從新渲染。
爲了不這種狀況,能夠將.bind
方法前置,改在constructor
中預先綁定,這樣onClick
將指向一個固定的函數,例子:
class PublicClassFields extends React.Component { constructor (props) { super(props) this.state = { data: Foo } this.changeData = this.changeData.bind(this) } ... ... }
這樣的話,PureUser
在執行 changeData
後就不會被從新渲染了。
後續還會有一些關於 react 性能相關的內容補充進來,同時也會不斷的更新這個 repo中的實例。