組件的性能優(yōu)化 - 01.單組件性能優(yōu)化
本文主要關(guān)注在React組件的性能優(yōu)化的相關(guān)知識和原理上,便于對React單組件的性能優(yōu)化方式有一定的認(rèn)識和了解
屬性傳遞優(yōu)化
React的單組件性能優(yōu)化主要是聚焦在屬性傳遞的優(yōu)化上,屬性傳遞優(yōu)化的核心在于Javascript的賦值的本質(zhì)是引用賦值。
在Javascript中,{a: 1} !== {a: 1},因為他們在內(nèi)存中的地址并不相等,如果每次在組件渲染階段,都為屬性賦值創(chuàng)建新的對象,必然會造成性能開銷。
屬性傳遞優(yōu)化的主要關(guān)注點在:
- 函數(shù)傳遞的優(yōu)化
- 屬性傳遞優(yōu)化
函數(shù)傳遞優(yōu)化
在React中,函數(shù)賦值為了解決this指向的問題,主要有以下三種形式:
- 通過在構(gòu)造函數(shù)中
this.handleClick = this.handleClick.bind(this),并在模板中使用<button onClick="{this.handleClick}">Button</button> - 在模板中使用bind方法
<button onClick="{this.handleClick.bind(this)}">Button</button> - 在模板中使用箭頭函數(shù)
<button onClick="{() => this.handleClick}">Button</button>
這其中推薦使用方式1,不推薦使用方式2、3。因為在構(gòu)造函數(shù)中調(diào)用this.handleClick.bind()只會進行一次賦值,而在方法2中,在模板中調(diào)用的話,每次render渲染都會調(diào)用this.handleClick.bind創(chuàng)建一個新的函數(shù)句柄,方法3同理
屬性傳遞優(yōu)化
在React的‘模板’中,屬性傳值的過程中,并不推薦使用<Demo style="{{color: red}}" skill="{{name: 'react'}}"/>的方式進行值創(chuàng)建并傳值,原因同上,即在每次調(diào)用react方法的時候都會創(chuàng)建新的對象{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: '單組件性能優(yōu)化',
}
console.log('構(gòu)造函數(shù)執(zhí)行中')
this.handleClick = this.handleClick.bind(this)
this.skill = {name: 'react'}
}
handleClick () {
this.setState({
num: this.state.num + 1
})
}
render () {
console.log('渲染函數(shù)執(zhí)行中')
return (
<div>
<section>
<p>
<mark>推薦使用這種函數(shù)傳遞的方式,因為該函數(shù)只會在構(gòu)造函數(shù)中執(zhí)行一次</mark>
</p>
<button onClick={this.handleClick}>button01</button>
</section>
<section>
<p>
<mark>以下兩種函數(shù)傳遞的方式,均不是非常推薦,他們都會在組件的渲染階段,重新生成調(diào)用函數(shù),對性能造成一定的影響</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;
?