简单的说一下如何在 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中的实例。