组件的性能优化 - 01.单组件性能优化
本文主要关注在React组件的性能优化的相关知识和原理上,便于对React单组件的性能优化方式有一定的认识和了解
属性传递优化
React的单组件性能优化主要是聚焦在属性传递的优化上,属性传递优化的核心在于Javascript的赋值的本质是引用赋值。
在Javascript中,{a: 1} !== {a: 1}
,因为他们在内存中的地址并不相等,如果每次在组件渲染阶段,都为属性赋值创建新的对象,必然会造成性能开销。
属性传递优化的主要关注点在:
- 函数传递的优化
- 属性传递优化
函数传递优化
在React中,函数赋值为了解决this指向的问题,主要有以下三种形式:
- 通过在构造函数中
this.handleClick = this.handleClick.bind(this)
,并在模板中使用<button onClick="{this.handleClick}">Button</button>
- 在模板中使用bind方法
<button onClick="{this.handleClick.bind(this)}">Button</button>
- 在模板中使用箭头函数
<button onClick="{() => this.handleClick}">Button</button>
这其中推荐使用方式1,不推荐使用方式2、3。因为在构造函数中调用this.handleClick.bind()
只会进行一次赋值,而在方法2中,在模板中调用的话,每次render渲染都会调用this.handleClick.bind
创建一个新的函数句柄,方法3同理
属性传递优化
在React的‘模板’中,属性传值的过程中,并不推荐使用<Demo style="{{color: red}}" skill="{{name: 'react'}}"/>
的方式进行值创建并传值,原因同上,即在每次调用react方法的时候都会创建新的对象{color: 'red'}
,通常将页面中不需要不变化的属性传递放置在constructor
中进行。
其次,在React中也并不推荐盲目使用扩展运算符,进行传值。(result="{...this.state}"
),原因在于,子组件中并不需要全部值的时候,使用扩展运算符将对象属性完整透传到子组件中也会造成多余的性能开销。
示例:
import React, {Component} from 'react';
import './App.css';
class App extends Component {
constructor(props) {
super(props)
this.state = {
num: 1,
age: 20,
title: '单组件性能优化',
}
console.log('构造函数执行中')
this.handleClick = this.handleClick.bind(this)
this.skill = {name: 'react'}
}
handleClick () {
this.setState({
num: this.state.num + 1
})
}
render () {
console.log('渲染函数执行中')
return (
<div>
<section>
<p>
<mark>推荐使用这种函数传递的方式,因为该函数只会在构造函数中执行一次</mark>
</p>
<button onClick={this.handleClick}>button01</button>
</section>
<section>
<p>
<mark>以下两种函数传递的方式,均不是非常推荐,他们都会在组件的渲染阶段,重新生成调用函数,对性能造成一定的影响</mark>
</p>
<button onClick={this.handleClick.bind(this)}>button02</button><br/>
<button onClick={() => this.handleClick}>button03</button>
</section>
<br></br>
<mark>这种传值方式也不推荐,因为每次都会在渲染阶段生成一个新的对象,从而造成性能开销</mark>
<Demo style={{color: 'red'}} skill={{name: 'react'}}></Demo>
<Demo style={{color: 'red'}} skill={this.skill}></Demo>
<mark>不推荐的传值方式,如果组件中只需要属性title,而扩展运算符会将state中额外的属性一并传递给组件,从而造成性能开销</mark>
<Demo {...this.state} skill={{name: 'react'}}></Demo>
</div>
)
}
}
function Demo (props) {
return (
<div>
<h2>I am a Demo</h2>
<h3>{props.title}</h3>
<h3>{props.skill.name}</h3>
</div>
)
}
export default App;
�