<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          10個(gè)小技巧幫助你提高React界面性能

          共 4068字,需瀏覽 9分鐘

           ·

          2021-06-13 11:39

          作者:Matthew Tyson
          來(lái)自:http://developer.51cto.com/art/202105/661918.htm

          眾所周知,沒(méi)有人會(huì)喜歡響應(yīng)緩慢的Web界面。而作為最受歡迎的JavaScript框架之一,react提供了多種提高UI性能的方法。下面讓我們一探究竟吧。
          總的說(shuō)來(lái),React是通過(guò)維護(hù)視圖中的內(nèi)存(in-memory)模型來(lái)運(yùn)作的。這通常被稱為虛擬DOM,它可以被用來(lái)確定實(shí)際DOM何時(shí)需要被更新。
          不過(guò),由于操控實(shí)際DOM的成本較高,因此我們需要確保僅在必要時(shí)才去更新DOM,進(jìn)而提高整體性能。
          為了從React框架中獲取最高性能,并提升React界面的響應(yīng)效率,本文將從各種功能函數(shù)(如Suspense)、以及基于類的組件出發(fā),和您討論十項(xiàng)常用的、面向DOM的技術(shù)與方法。

          shouldComponentUpdate

          在編寫基于類的組件時(shí),您可以重寫shouldComponentUpdate()的生命周期方法。該方法的目的在于:明確地聲明目標(biāo)組件是否需要被重新渲染(re-rendering)。
          值得注意的是,在更新實(shí)際DOM的生命周期中,渲染的開銷是非常巨大的。
          因此,只有在組件的屬性(props)或狀態(tài)(states)發(fā)生變化時(shí),我們才需要讓React執(zhí)行渲染。
          有時(shí)您甚至可以跳過(guò)渲染,以避免整體調(diào)用所產(chǎn)生的開銷。
          shouldComponentUpdate的簽名和操作比較簡(jiǎn)單。在如下簡(jiǎn)單示例中,組件需要知曉應(yīng)該在何種指定觸發(fā)條件下,去執(zhí)行更新。
          該方法將接收到的屬性與狀態(tài)當(dāng)作參數(shù),如果返回為true,組件將執(zhí)行渲染,否則并不觸發(fā)渲染。
          shouldComponentUpdate(nextProps, nextState) {     if (this.props.significant !== nextProps.significant) {       return true;     }     return false;   }

          雖然上述代碼段主要檢查的是屬性,但是它對(duì)于狀態(tài)也同樣適用。當(dāng)然,在實(shí)際應(yīng)用中,對(duì)于屬性或狀態(tài)的檢查,并判定是否返回true,可能會(huì)更加復(fù)雜。

          如果您需要比較某個(gè)簡(jiǎn)單的淺層值(shallow value),那么請(qǐng)使用下一個(gè)技巧--PureComponent。

          PureComponent

          如果您的組件僅需要對(duì)屬性和狀態(tài)進(jìn)行簡(jiǎn)單的淺層比較(shallow comparison,https://stackoverflow.com/a/5703797/467240),以確定是否需要渲染,那么完全可以使用PureComponent之類的擴(kuò)展基類--class MyComponent extends React.PureComponent。

          它可以實(shí)現(xiàn):當(dāng)通過(guò)淺層比較,并未發(fā)現(xiàn)屬性或狀態(tài)發(fā)生了任何變化時(shí),render()就不會(huì)被調(diào)用。

          顧名思義,PureComponent表示:僅在屬性或狀態(tài)改變時(shí),才會(huì)觸發(fā)輸出的更改,因此該組件是純凈的,不會(huì)帶有任何副作用。

          useEffect

          前面的技巧僅適用于那些基于類的組件。為了達(dá)到與常規(guī)功能性組件相似的效果,您可以使用useEffect hook和memo之類的功能性組件。

          其中,useEffect與shouldComponentUpdate有著相似的效果,它允許用戶指定:僅在某些變量發(fā)生更改的情況下,生效某種特定的功能 ,從而避免了整體變更的開銷。下面是一個(gè)簡(jiǎn)單的useEffect示例:

          const MyComponent = (props) => {   useEffect(() => {     console.info("Update Complete: " + props.significantvariable);   }, [props.significantvariable]); }

          由上述代碼段可知,如果props.significantVariable已被更改(即變量發(fā)生了變化),那么該代碼就會(huì)運(yùn)行生效。

          用React.memo提供記憶

          作為一個(gè)高階組件,memo包裝了各種組件,并擴(kuò)展了它們的行為能力。也就是說(shuō),如果功能性組件具有相同的屬性,memo便能夠以緩沖的方式,“記住”它們的結(jié)果。

          據(jù)此,它可以有效地防止功能性組件在無(wú)視屬性是否一致的情況下,去盲目地執(zhí)行渲染。

          為了模仿PureComponent只關(guān)注屬性的行為,我們可以使用如下代碼段來(lái)包裝某些功能性組件,使其只檢查屬性的更改,而非狀態(tài)。

          由于屬性和狀態(tài)是不同的,因此通過(guò)比較,一旦props.quote被認(rèn)定為未發(fā)生改變,則其對(duì)應(yīng)的組件也不會(huì)重新渲染。

          const MyComponent = (props) => {   return <span>props.quote</span> } export default React.memo(SomeComponent)

          同時(shí),React.memo 可以通過(guò)第二個(gè)參數(shù),來(lái)檢查函數(shù)的等效性:

          export default React.memo(MyComponent, (oldProps, newProps) => {} );

          通過(guò)上述代碼,我們可以實(shí)現(xiàn)對(duì)用例新的和舊的屬性進(jìn)行比較。如果屬性相等,該函數(shù)則返回true。

          值得注意的是,這與我們?cè)谇懊娼榻B的shouldComponentUpdate,在發(fā)現(xiàn)組件出現(xiàn)更新時(shí)返回true,正好相反。

          窗口化(列表虛擬化)

          現(xiàn)在,讓我們將注意力轉(zhuǎn)移到一項(xiàng)同時(shí)適用于功能性和類組件的技術(shù)--窗口化(windowing)上。

          例如有一個(gè)具有數(shù)千行記錄的數(shù)據(jù)表或列表,如果您想在該表所對(duì)應(yīng)的應(yīng)用界面上顯示大量數(shù)據(jù)集,那么就需要采用“窗口化”的方式來(lái)查詢數(shù)據(jù)。

          也就是說(shuō),我們可以通過(guò)一次性僅加載和顯示部分?jǐn)?shù)據(jù)的形式,防止大量數(shù)據(jù)“卡死”應(yīng)用的用戶界面(UI)。

          為此,我們時(shí)常可以用到react-window庫(kù)(請(qǐng)參見(jiàn)--https://github.com/bvaughn/react-window)。

          函數(shù)緩存

          如果您覺(jué)得函數(shù)調(diào)用的成本過(guò)高,那么可以考慮對(duì)其進(jìn)行緩存。

          如果各個(gè)參數(shù)相同,而且緩存能夠返回結(jié)果,我們就可以使用存儲(chǔ)式緩存(memorized cache)的方式,來(lái)避免各種針對(duì)數(shù)據(jù)獲取的調(diào)用。

          當(dāng)然,函數(shù)緩存是否真的適用,還取決于函數(shù)的具體特征。

          延遲加載和代碼拆分

          所謂延遲加載是指:我們僅在必要時(shí),才去加載數(shù)據(jù)。React 16.6引入了React.lazy(),它允許用戶對(duì)代碼按需進(jìn)行拆分。

          這意味著,您可以在使用常規(guī)組件語(yǔ)法的同時(shí),獲得各種延遲加載的語(yǔ)義。

          當(dāng)然,React 16.6之前的版本,并非無(wú)法實(shí)現(xiàn)代碼拆分,只是在處置大型代碼庫(kù)時(shí),相對(duì)比較繁瑣。

          并發(fā)模式、Suspense和useDeferredValue

          作為React 16的一項(xiàng)最顯著的新功能, 并發(fā)模式 可以讓用戶通過(guò)使用Suspense組件,實(shí)現(xiàn)數(shù)據(jù)獲取和渲染的并行處理,進(jìn)而極大地提高應(yīng)用程序的實(shí)際感知性能。

          我們除了能夠用Suspense組件來(lái)定義數(shù)據(jù)的獲取區(qū)域之外,還可以使用諸如useDeferredValue等由React 16帶來(lái)的新組件,來(lái)提升自動(dòng)建議(auto-suggest)等工作方式,進(jìn)而避免用戶碰到諸如錯(cuò)誤性的鍵入等不良的體驗(yàn)。

          數(shù)據(jù)獲取的防抖(Debounce)和限流(throttle)

          大多數(shù)情況下,我們可以通過(guò)debounce或throttle函數(shù),來(lái)更好地處理React的并發(fā)模式。

          如果您的代碼庫(kù)被鎖定為舊版的渲染引擎,而無(wú)法開啟并發(fā)模式時(shí),此類函數(shù)便可以有效地避免在數(shù)據(jù)獲取的過(guò)程中,出現(xiàn)混亂的局面。

          例如,如果您想在用戶鍵入數(shù)據(jù)的同時(shí),實(shí)時(shí)地獲取他們的輸入,那么由于每個(gè)擊鍵都會(huì)觸發(fā)一個(gè)請(qǐng)求,因此整體的性能會(huì)大打折扣。

          對(duì)此,我們便可以使用debounce或throttle函數(shù),來(lái)緩解此類問(wèn)題。

          分析(Profiling)

          除了上面提到的技術(shù),我們還可以通過(guò)對(duì)應(yīng)用程序進(jìn)行性能分析,來(lái)獲悉性能瓶頸的所在,并驗(yàn)證上述改進(jìn)方法的實(shí)際效果。

          目前,像Chrome和Firefox之類的瀏覽器,都帶有內(nèi)置的分析器(profiler)。一旦啟用了React的開發(fā)模式(dev mode),您將可以通過(guò)分析器,來(lái)查看某些正在使用的特定組件。

          這對(duì)于檢查網(wǎng)絡(luò)的狀態(tài),以及識(shí)別后端調(diào)用的延遲,都是非常實(shí)用的。據(jù)此,您可以清晰地判斷出,到底是前端JavaScript的代碼問(wèn)題,還是存在著需要后端修復(fù)的缺陷。

          此外,React 16.5以及更高的版本,還提供了一個(gè)名為DevTools Profiler(https://reactjs.org/blog/2018/09/10/introducing-the-react-profiler.html)的工具。

          它既能夠?yàn)樘幱诓l(fā)模式的各個(gè)函數(shù),提供了更加詳盡的服務(wù)功能與集成;又可以通過(guò)多種方法,對(duì)應(yīng)用程序的行為活動(dòng)進(jìn)行切片(slice)和切塊(dice)。

          另一類 Profiler組件 則能夠展現(xiàn)組件渲染生命周期中的各種詳細(xì)信息。

          React的生產(chǎn)環(huán)境構(gòu)建

          最后,在部署生產(chǎn)環(huán)境時(shí),您還需要確保生產(chǎn)環(huán)境構(gòu)建(production build)的精簡(jiǎn)性、且不包含任何開發(fā)調(diào)試過(guò)程中的日志記錄。

          當(dāng)然,具體步驟取決于您所使用的構(gòu)建工具。如果您使用的是Create React App,則請(qǐng)參考--https://create-react-app.dev/docs/production-build/。


          學(xué)習(xí)更多技能

          請(qǐng)點(diǎn)擊下方公眾號(hào)

          瀏覽 36
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  成人在线看mv | 一级片色情 | 日韩一级一 | 中文av字幕 | 高清无码爱爱视频 |