1:不要在JSX中写内联函数,这样性能有所损耗。比如
//No
<SotpButton
onClick={()=>{this._onClick()}}
/>
//YES
constructor(){
this._onClick = this._onClick.bind(this) //或者使用bind operator(版本稳定的话), thsi.onClick = :: this.onClick
}
_onClick(){
}
render(){
return (
<SotpButton
onClick={this._onClick}
/>
)
}
原因有二:
- 每一次渲染这段JSX,都会产生新的函数对象
- 每一次传给SotpButton的props都是新的,这样SotpButton无法通过shouldComponentUpdate对props的检查来避免re-render
2:聪明组件和傻瓜组件
软件设计有一个原则,叫做“责任分离”,就是一个模块的责任尽量小,如果一个模块的功能过多,就分拆成多个模块,让一个模块专注于一个功能。
根据 UI = f(data) 公式。使用React做UI界面,无非是获取驱动界面的数据,然后进行数据渲染界面。把获取和管理数据的逻辑放在父组件,即聪明组件;把渲染界面的逻辑放在子组件,即傻瓜组件。这样的好处是如果管理数据的方式需要从redux改成mobx,那只需要修改聪明组件即可。
3:PureComponent结合immutable.js
PureComponent是在内部封装了shouldComponentUpdate的方法,每次组件的state或者props发生变化时,render都会重新执行。shouldComponentUpdate会在render函数执行之前被调用,如果返回true,就继续,如果返回false,渲染过程就立刻停止。
但是PureComponent和shouldComponentUpdate都对props做浅比较,不是深比较,所以props是一个深层对象的话,就容易产生问题。比如两次渲染传入的是同一个对象,只是对象中的某个属性值不同。但是在PureComponent和shouldComponentUpdate看来,props没有发生变化,所以不会重新渲染,这就尴尬了。这就可以使用immutable.js(like Flow or TypeScript)来解决这个问题。
reactjs.org关于react性能优化的docs https://reactjs.org/docs/optimizing-performance.html
4:React.memo()
虽然shouldComponentUpdate能够避免重复渲染,提高性能,但是如果子组件是一个纯函数呢?不继承React.Component,不是class, 那么它也就没有shouldComponentUpdate。So,React16.6.0版本更新了一个重要的功能React.memo()。
React.memo()是一个高阶组件,它类似于PureComponent功能组件而不是class。React.memo()通过记忆化将函数返回结果存储起来,以提高性能。
const MyComponent = React.memo(function MyComponent(props) {
/* render using props */
});
维基百科: 在计算机领域,记忆化是一种主要用来提升计算机程序速度的优化技术方案。它将开销较大的函数调用的返回结果存储起来,当同样的输入再次发生时,则返回缓存好的数据,以此提升运算效率。