成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

淺談react性能優(yōu)化的方法

HitenDev / 1455人閱讀

摘要:函數(shù)綁定的方式一般有下面種方式綁定構(gòu)造函數(shù)中綁定然后可以使用時綁定使用箭頭函數(shù)以上三種方法,第一種最優(yōu)。因?yàn)榈谝环N構(gòu)造函數(shù)只在組件初始化的時候執(zhí)行一次,第二種組件每次都會執(zhí)行第三種在每一次時候都會生成新的箭頭函數(shù)。

這篇文章主要介紹了淺談react性能優(yōu)化的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

React性能優(yōu)化思路

軟件的性能優(yōu)化思路就像生活中去看病,大致是這樣的:

使用工具來分析性能瓶頸(找病根)

嘗試使用優(yōu)化技巧解決這些問題(服藥)

使用工具測試性能是否確實(shí)有提升(療效確認(rèn))

初識react只是為了盡快完成項(xiàng)目,后期進(jìn)行代碼審查時候發(fā)現(xiàn)有很多地方需要優(yōu)化,因此做了個小結(jié)。

Code Splitting

shouldComponentUpdate避免重復(fù)渲染

使用不可突變數(shù)據(jù)結(jié)構(gòu)

組件盡可能的進(jìn)行拆分、解耦

列表類組件優(yōu)化

bind函數(shù)優(yōu)化

不要濫用props

ReactDOMServer進(jìn)行服務(wù)端渲染組件

Code Splitting

Code Splitting 可以幫你“懶加載”代碼,如果你沒辦法直接減少應(yīng)用的體積,那么不妨嘗試把應(yīng)用從單個 bundle 拆分成單個 bundle + 多份動態(tài)代碼的形式。

webpack提供三種代碼分離方法,詳情見webpack官網(wǎng)

入口起點(diǎn):使用 entry 配置手動地分離代碼。

防止重復(fù):使用 SplitChunks 去重和分離 chunk。

動態(tài)導(dǎo)入:通過模塊的內(nèi)聯(lián)函數(shù)調(diào)用來分離代碼。

在此,主要了解一下第三種動態(tài)導(dǎo)入的方法。

1、例如可以把下面的import方式

`import { add } from` `"./math"``;`
`console.log(add(16, 26));`

改寫成動態(tài) import 的形式,讓首次加載時不去加載 math 模塊,從而減少首次加載資源的體積。
[?]了解更多
)

`import(``"./math"``).then(math => {`
`console.log(math.add(16, 26));`
`});`
2、例如引用react的高階組件react-loadable進(jìn)行動態(tài)import。

`import Loadable from` `"react-loadable"``;`
`import Loading from` `"./loading-component"``;`
`const LoadableComponent = Loadable({`
`loader: () => import(``"./my-component"``),`
`loading: Loading,`
`});`
`export` `default` `class App extends React.Component {`
`render() {`
`return` `;`
`}`
`}`

上面的代碼在首次加載時,會先展示一個 loading-component,然后動態(tài)加載 my-component 的代碼,組件代碼加載完畢之后,便會替換掉

loading-component
shouldComponentUpdate避免重復(fù)渲染

當(dāng)一個組件的props或者state改變時,React通過比較新返回的元素和之前渲染的元素來決定是否有必要更新實(shí)際的DOM。當(dāng)他們不相等時,React會更新DOM。

在一些情況下,你的組件可以通過重寫這個生命周期函數(shù)shouldComponentUpdate來提升速度, 它是在重新渲染過程開始前觸發(fā)的。 這個函數(shù)默認(rèn)返回true,可使React執(zhí)行更新。

為了進(jìn)一步說明問題,引用官網(wǎng)的圖解釋一下,如下圖( SCU表示shouldComponentUpdate,綠色表示返回true(需要更新),紅色表示返回false(不需要更新);vDOMEq表示虛擬DOM比對,綠色表示一致(不需要更新),紅色表示發(fā)生改變(需要更新)):

根據(jù)渲染流程,首先會判斷shouldComponentUpdate(SCU)是否需要更新。如果需要更新,則調(diào)用組件的render生成新的虛擬DOM,然后再與舊的虛擬DOM對比(vDOMEq),如果對比一致就不更新,如果對比不同,則根據(jù)最小粒度改變?nèi)ジ翫OM;如果SCU不需要更新,則直接保持不變,同時其子元素也保持不變。

C1根節(jié)點(diǎn),綠色SCU、紅色vDOMEq,表示需要更新。

C2節(jié)點(diǎn),紅色SCU,表示不需要更新,同時

C4、C5作為其子節(jié)點(diǎn)也不需要檢查更新。

C3節(jié)點(diǎn),綠色SCU、紅色vDOMEq,表示需要更新。

C6節(jié)點(diǎn),綠色SCU、紅色vDOMEq,表示需要更新。

C7節(jié)點(diǎn),紅色SCU,表示不需要更新。

C8節(jié)點(diǎn),綠色SCU,表示React需要渲染這個組件;綠色vDOMEq,表示虛擬DOM一致,不更新DOM。

因此,我們可以通過根據(jù)自己的業(yè)務(wù)特性,重載shouldComponentUpdate,只在確認(rèn)真實(shí)DOM需要改變時,再返回true。一般的做法是比較組件的props和state是否真的發(fā)生變化,如果發(fā)生變化則返回true,否則返回false。引用官網(wǎng)的案例。

`class CounterButton extends React.Component {`
`constructor(props) {`
`super``(props);`
`this``.state = {count: 1};`
`}`
`shouldComponentUpdate(nextProps, nextState) {`
`if` `(``this``.props.color !== nextProps.color) {`
`return` `true``;`
`}`
`if` `(``this``.state.count !== nextState.count) {`
`return` `true``;`
`}`
`return` `false``;`
`}`
`render() {`
`return` `(`
`` `this``.setState(state => ({count: state.count + 1}))}>`
`Count: {``this``.state.count}`
``
`);`
`}`
`}`

在以上代碼中,shouldComponentUpdate只檢查props.color和state.count的變化。如果這些值沒有變化,組件就不會更新。當(dāng)你的組件變得更加復(fù)雜時,你可以使用類似的模式來做一個“淺比較”,用來比較屬性和值以判定是否需要更新組件。這種模式十分常見,因此React提供了一個輔助對象來實(shí)現(xiàn)這個邏輯 - 繼承自React.PureComponent。

大部分情況下,你可以使用React.PureComponent而不必寫你自己的shouldComponentUpdate,它只做一個淺比較。但是當(dāng)你比較的目標(biāo)為引用類型數(shù)據(jù),淺比較會忽略屬性或狀態(tài)突變的情況,此時你不能使用它,此時你需要關(guān)注下面的不可突變數(shù)據(jù)。

附:數(shù)據(jù)突變(mutated)是指變量的引用沒有改變(指針地址未改變),但是引用指向的數(shù)據(jù)發(fā)生了變化(指針指向的數(shù)據(jù)發(fā)生變更)。例如const x = {foo:"foo"}。x.foo="none" 就是一個突變。

使用不可突變數(shù)據(jù)結(jié)構(gòu)

引用官網(wǎng)中的例子解釋一下突變數(shù)據(jù)產(chǎn)生的問題。例如,假設(shè)你想要一個ListOfWords組件來渲染一個逗號分隔的單詞列表,并使用一個帶了點(diǎn)擊按鈕名字叫WordAdder的父組件來給子列表添加一個單詞。以下代碼并不正確:

`class ListOfWords extends React.PureComponent {`
`render() {`
`return` `
{``this``.props.words.join(``","``)}
;` `}` `}` `class WordAdder extends React.Component {` `constructor(props) {` `super``(props);` `this``.state = {` `words: [``"marklar"``]` `};` `this``.handleClick =` `this``.handleClick.bind(``this``);` `}` `handleClick() {` `// 這段內(nèi)容將會導(dǎo)致代碼不會按照你預(yù)期的結(jié)果運(yùn)行` `const words =` `this``.state.words;` words.push(``"marklar"``);` `this``.setState({words: words});` `}` `render() {` `return` `(` `
` `
` `);` `}` `}`

導(dǎo)致代碼無法正常工作的原因是 PureComponent 僅僅對 this.props.words的新舊值進(jìn)行“淺比較”。在words值在handleClick中被修改之后,即使有新的單詞被添加到數(shù)組中,但是this.props.words的新舊值在進(jìn)行比較時是一樣的(引用對象比較),因此 ListOfWords 一直不會發(fā)生渲染。
避免此類問題最簡單的方式是避免使用值可能會突變的屬性或狀態(tài),如:
1、數(shù)組使用concat,對象使用Object.assign()

`handleClick() {`
`this``.setState(prevState => ({`
`words: prevState.words.concat([``"marklar"``])`
`}));`
`}`
`// 假設(shè)我們有一個叫colormap的對象,下面方法不污染原始對象`
`function` `updateColorMap(colormap) {`
`return` `Object.assign({}, colormap, {right:` `"blue"``});`
`}`

2、ES6支持?jǐn)?shù)組或?qū)ο蟮膕pread語法

`handleClick() {`
`this``.setState(prevState => ({`
`words: [...prevState.words,` `"marklar"``],`
`}));`
`};`
`function` `updateColorMap(colormap) {`
`return` `{...colormap, right:` `"blue"``};`
`}`

3、使用不可突變數(shù)據(jù)immutable.js

immutable.js使得變化跟蹤很方便。每個變化都會導(dǎo)致產(chǎn)生一個新的對象,因此我們只需檢查索引對象是否改變。

`const SomeRecord = Immutable.Record({ foo:` `null` `});`
`const x =` `new` `SomeRecord({ foo:` `"bar"` `});`
`const y = x.set(``"foo"``,` `"baz"``);`
`x === y;` `// false`

在這個例子中,x突變后返回了一個新的索引,因此我們可以安全的確認(rèn)x被改變了。

不可突變的數(shù)據(jù)結(jié)構(gòu)幫助我們輕松的追蹤對象變化,從而可以快速的實(shí)現(xiàn)shouldComponentUpdate。

具體如何使用可參考下面文章:Immutable 詳解及 React 中實(shí)踐

組件盡可能的進(jìn)行拆分、解耦

組件盡可能的細(xì)分,比如一個input+list組件,可以將list分成一個PureComponent,只在list數(shù)據(jù)變化時更新。否則在input值變化頁面重新渲染的時候,list也需要進(jìn)行不必要的DOM diff。
列表類組件優(yōu)化

key屬性在組件類之外提供了另一種方式的組件標(biāo)識。通過key標(biāo)識,在組件發(fā)生增刪改、排序等操作時,可以根據(jù)key值的位置直接調(diào)整DOM順序,告訴React 避免不必要的渲染而避免性能的浪費(fèi)。
例,對于一個基于排序的組件渲染:

`var` `items = sortBy(``this``.state.sortingAlgorithm,` `this``.props.items);`
`return` `items.map(``function``(item){`
`return` ``
`});`

當(dāng)順序發(fā)生改變時,React 會對元素進(jìn)行diff操作,并改img的src屬性。顯示,這樣的操作效率是非常低的。這時,我們可以為組件添加一個key屬性以唯一的標(biāo)識組件:
return
增加key后,React就不是diff,而是直接使用insertBefore操作移動組件位置,而這個操作是移動DOM節(jié)點(diǎn)最高效的辦法。
bind函數(shù)

綁定this的方式:一般有下面3種方式:

1、constructor綁定
`constructor(props) {`
`super``(props);`
`this``.handleClick =` `this``.handleClick.bind(``this``);` `//構(gòu)造函數(shù)中綁定`
`}`
`//然后可以`
`

`

2、使用時綁定

`<``p` `onClick={this.handleClick.bind(this)}>`

3、使用箭頭函數(shù)

`<``Test` `click={() => { this.handleClick() }}/>`

以上三種方法,第一種最優(yōu)。

因?yàn)榈谝环N構(gòu)造函數(shù)只在組件初始化的時候執(zhí)行一次,

第二種組件每次render都會執(zhí)行

第三種在每一次render時候都會生成新的箭頭函數(shù)。例:Test組件的click屬性是個箭頭函數(shù),組件重新渲染的時候Test組件就會

因?yàn)檫@個新生成的箭頭函數(shù)而進(jìn)行更新,從而產(chǎn)生Test組件的不必要渲染。

不要濫用props

props盡量只傳需要的數(shù)據(jù),避免多余的更新,盡量避免使用{...props}
ReactDOMServer進(jìn)行服務(wù)端渲染組件

為了用戶會更快速地看到完整渲染的頁面,可以采用服務(wù)端渲染技術(shù),在此了解一下ReactDOMServer。

為了實(shí)現(xiàn)SSR,你可能會用nodejs框架(Express、Hapi、Koa)來啟動一個web服務(wù)器,接著調(diào)用 renderToString 方法去渲染你的根組件成為字符串,最后你再輸出到 response。

`// using Express`
`import { renderToString } from` `"react-dom/server"``;`
`import MyPage from` `"./MyPage"``;`
`app.get(``"/"``, (req, res) => {`
`res.write(``"My Page"``);`
`res.write(``"
"``);` `res.write(renderToString());` `res.write(``"
"``);` `res.end();` `});`

客戶端使用render方法來生成HTML

import ReactDOM from "react-dom"`;`
import MyPage from "./MyPage"`;`
ReactDOM.render(, document.getElementById(`"app"`));
react性能檢測工具

react16版本之前,我們可以使用react-addons-perf工具來查看,而在最新的16版本,我們只需要在url后加上?react_pref。

首先來了解一下react-addons-perf。

react-addons-perf這是 React 官方推出的一個性能工具包,可以打印出組件渲染的時間、次數(shù)、浪費(fèi)時間等。

簡單說幾個api,具體用法可參考官網(wǎng):

Perf.start() 開始記錄

Perf.stop() 結(jié)束記錄

Perf.printInclusive() 查看所有設(shè)計到的組件render

Perf.printWasted() 查看不需要的浪費(fèi)組件render

再來了解一下,react16版本的方法,在url后加上?react_pref,就可以在chrome瀏覽器的performance,我們可以查看User Timeing來查看組件的加載時間。點(diǎn)擊record開始記錄,注意記錄時長不要超過20s,否則可能導(dǎo)致chrome掛起。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/108603.html

相關(guān)文章

  • 淺談React性能優(yōu)化方向

    摘要:主要討論性能優(yōu)化的主要方向和一些小技巧。如果你覺得可以,請多點(diǎn)贊,鼓勵我寫出更精彩的文章 本文來源于公司內(nèi)部的一次閃電分享,稍作潤色分享出來。主要討論 React 性能優(yōu)化的主要方向和一些小技巧。如果你覺得可以,請多點(diǎn)贊,鼓勵我寫出更精彩的文章

    lingdududu 評論0 收藏0
  • 2017文章總結(jié)

    摘要:歡迎來我的個人站點(diǎn)性能優(yōu)化其他優(yōu)化瀏覽器關(guān)鍵渲染路徑開啟性能優(yōu)化之旅高性能滾動及頁面渲染優(yōu)化理論寫法對壓縮率的影響唯快不破應(yīng)用的個優(yōu)化步驟進(jìn)階鵝廠大神用直出實(shí)現(xiàn)網(wǎng)頁瞬開緩存網(wǎng)頁性能管理詳解寫給后端程序員的緩存原理介紹年底補(bǔ)課緩存機(jī)制優(yōu)化動 歡迎來我的個人站點(diǎn) 性能優(yōu)化 其他 優(yōu)化瀏覽器關(guān)鍵渲染路徑 - 開啟性能優(yōu)化之旅 高性能滾動 scroll 及頁面渲染優(yōu)化 理論 | HTML寫法...

    dailybird 評論0 收藏0
  • 2017文章總結(jié)

    摘要:歡迎來我的個人站點(diǎn)性能優(yōu)化其他優(yōu)化瀏覽器關(guān)鍵渲染路徑開啟性能優(yōu)化之旅高性能滾動及頁面渲染優(yōu)化理論寫法對壓縮率的影響唯快不破應(yīng)用的個優(yōu)化步驟進(jìn)階鵝廠大神用直出實(shí)現(xiàn)網(wǎng)頁瞬開緩存網(wǎng)頁性能管理詳解寫給后端程序員的緩存原理介紹年底補(bǔ)課緩存機(jī)制優(yōu)化動 歡迎來我的個人站點(diǎn) 性能優(yōu)化 其他 優(yōu)化瀏覽器關(guān)鍵渲染路徑 - 開啟性能優(yōu)化之旅 高性能滾動 scroll 及頁面渲染優(yōu)化 理論 | HTML寫法...

    hellowoody 評論0 收藏0

發(fā)表評論

0條評論

HitenDev

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<