React 在不做任何优化的情况下性能也非常好,然而通过一些小小的优化,可以让性能进一步提升,通过以下这6条建议,可以数十倍加快渲染速度
React 在开发环境下,有完整的警告和错误检查,但它们不是为生产环境准备的,如果你看过 React 的源码,你会看到很多 if (process.env.NODE_ENV != 'production')
,这些代码对于最终用户是不需要的,而且访问 process.env.NODE_ENV
会非常慢,对于生产环境而言,完全可以移除这些代码
如果你使用 Webpack
,你可以使用 DefinePlugin
来替换 process.env.NODE_ENV
为 'production',然后使用 UglifyJsPlugin
移除这些不会执行的代码
// webpack.config.js ... plugins: [ new webpack.DefinePlugin({ 'process.env.NODE_ENV': JSON.stringify('production') }), new webpack.optimize.UglifyJsPlugin({ compress: { warnings: false } }) ] ...
在 React 15 的更新
中非常重要的一项是,使用在现代化浏览器中性能更好的 document.createElement
替换 innerHTML
,这一改动也意味着 React 将不再支持 IE8
Babel 为开发者们提供了 React Constant Elements 和 React Inline Elements ,这两款插件能够在编译阶段将代码转换成更高效的形式,注意仅将它们用于生产环境
这一点在循环渲染集合组件时尤其重要,React 在渲染大型集合是性能十分糟糕,原因是 React 会在每次更新中全部重新渲染,因此建议将渲染集合的部分装为独立的组件渲染
// Bad class MyComponent extends Component { render() { const {todos, user} = this.props; return (<div> {user.name} <ul> {todos.map(todo => <TodoView todo={todo} key={todo.id} />)} </ul> </div>) } }
// Good // 当 user.name 更新时,列表不会重新渲染 class MyComponent extends Component { render() { const {todos, user} = this.props; return (<div> {user.name} <TodosView todos={todos} /> </div>) } } class TodosView extends Component { render() { const {todos} = this.props; return (<ul> {todos.map(todo => <TodoView todo={todo} key={todo.id} />)} </ul>) } }
在 render() 中绑定的方法应该尽早声明,而不是在渲染时定义
// Bad render() { return <MyWidget onClick={() => { alert(this.state.text) }} /> }
// Good constructor() { this.handleClick = this.handleClick.bind(this); } handleClick() { alert(this.state.text); } render() { return <MyWidget onClick={this.handleClick} /> }
对于不需要更新的组件,可以在 shouldComponentUpdate()
中 return false
,或者使用 Stateless Component
// Bad class Logo extends Component { render() { return <div><img src='logo.png' /></div>; } }
// Good class Logo extends Component { shouldComponentUpdate() { return false; } render() { return <div><img src='logo.png' /></div>; } } // or Stateless Component const Logo = () => <div><img src='logo.png' /></div>;