組件的性能優(yōu)化 - 01.單組件性能優(yōu)化
本文主要關(guān)注在React組件的性能優(yōu)化的相關(guān)知識(shí)和原理上,便于對(duì)React單組件的性能優(yōu)化方式有一定的認(rèn)識(shí)和了解
屬性傳遞優(yōu)化
React的單組件性能優(yōu)化主要是聚焦在屬性傳遞的優(yōu)化上棚贾,屬性傳遞優(yōu)化的核心在于Javascript的賦值的本質(zhì)是引用賦值窖维。
在Javascript中,{a: 1} !== {a: 1}
妙痹,因?yàn)樗麄冊(cè)趦?nèi)存中的地址并不相等铸史,如果每次在組件渲染階段,都為屬性賦值創(chuàng)建新的對(duì)象怯伊,必然會(huì)造成性能開銷琳轿。
屬性傳遞優(yōu)化的主要關(guān)注點(diǎ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琉闪。因?yàn)樵跇?gòu)造函數(shù)中調(diào)用this.handleClick.bind()
只會(huì)進(jìn)行一次賦值,而在方法2中寇甸,在模板中調(diào)用的話塘偎,每次render渲染都會(huì)調(diào)用this.handleClick.bind
創(chuàng)建一個(gè)新的函數(shù)句柄,方法3同理
屬性傳遞優(yōu)化
在React的‘模板’中拿霉,屬性傳值的過程中吟秩,并不推薦使用<Demo style="{{color: red}}" skill="{{name: 'react'}}"/>
的方式進(jìn)行值創(chuàng)建并傳值,原因同上绽淘,即在每次調(diào)用react方法的時(shí)候都會(huì)創(chuàng)建新的對(duì)象{color: 'red'}
涵防,通常將頁面中不需要不變化的屬性傳遞放置在constructor
中進(jìn)行。
其次沪铭,在React中也并不推薦盲目使用擴(kuò)展運(yùn)算符壮池,進(jìn)行傳值。(result="{...this.state}"
)杀怠,原因在于椰憋,子組件中并不需要全部值的時(shí)候,使用擴(kuò)展運(yùn)算符將對(duì)象屬性完整透?jìng)鞯阶咏M件中也會(huì)造成多余的性能開銷赔退。
示例:
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ù)傳遞的方式橙依,因?yàn)樵摵瘮?shù)只會(huì)在構(gòu)造函數(shù)中執(zhí)行一次</mark>
</p>
<button onClick={this.handleClick}>button01</button>
</section>
<section>
<p>
<mark>以下兩種函數(shù)傳遞的方式证舟,均不是非常推薦,他們都會(huì)在組件的渲染階段窗骑,重新生成調(diào)用函數(shù)女责,對(duì)性能造成一定的影響</mark>
</p>
<button onClick={this.handleClick.bind(this)}>button02</button><br/>
<button onClick={() => this.handleClick}>button03</button>
</section>
<br></br>
<mark>這種傳值方式也不推薦,因?yàn)槊看味紩?huì)在渲染階段生成一個(gè)新的對(duì)象创译,從而造成性能開銷</mark>
<Demo style={{color: 'red'}} skill={{name: 'react'}}></Demo>
<Demo style={{color: 'red'}} skill={this.skill}></Demo>
<mark>不推薦的傳值方式抵知,如果組件中只需要屬性title,而擴(kuò)展運(yùn)算符會(huì)將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;
?