偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

React 性能優(yōu)化技巧總結(jié)

新聞 前端
本文將從 render 函數(shù)的角度總結(jié) React App 的優(yōu)化技巧。文中將涉及 React 16.8.2 版本的內(nèi)容(也即 Hooks),因此請(qǐng)至少了解 useState 以保證食用效果。

[[258068]]

本文將從 render 函數(shù)的角度總結(jié) React App 的優(yōu)化技巧。需要提醒的是,文中將涉及 React 16.8.2 版本的內(nèi)容(也即 Hooks),因此請(qǐng)至少了解 useState 以保證食用效果。

正文開(kāi)始。

當(dāng)我們討論 React App 的性能問(wèn)題時(shí),組件的 渲染 速度是一個(gè)重要問(wèn)題。在進(jìn)入到具體優(yōu)化建議之前,我們先要理解以下 3 點(diǎn):

  1. 當(dāng)我們?cè)谡f(shuō)「render」時(shí),我們?cè)谡f(shuō)什么?
  2. 什么時(shí)候會(huì)執(zhí)行「render」?
  3. 在「render」過(guò)程中會(huì)發(fā)生什么?

解讀 render 函數(shù)

這部分涉及 reconciliation 和 diffing 的概念,當(dāng)然官方文檔在 這里 。

當(dāng)我們?cè)谡f(shuō)「render」時(shí),我們?cè)谡f(shuō)什么?

這個(gè)問(wèn)題其實(shí)寫(xiě)過(guò) React 的人都會(huì)知道,這里再簡(jiǎn)單說(shuō)下:

在 class 組件中,我們指的是 render 方法:

  1. class Foo extends React.Component {  
  2.  render() {  
  3.    return <h1> Foo </h1>;  
  4.  }  
  5. }  

在函數(shù)式組件中,我們指的是函數(shù)組件本身:

  1. function Foo() {  
  2.   return <h1> Foo </h1>;  
  3. }  

什么時(shí)候會(huì)執(zhí)行「render」?

render 函數(shù)會(huì)在兩種場(chǎng)景下被調(diào)用:

1. 狀態(tài)更新時(shí)

a. 繼承自 React.Component 的 class 組件更新?tīng)顟B(tài)時(shí)

  1. import React from "react";  
  2. import ReactDOM from "react-dom";  
  3.   
  4. class App extends React.Component {  
  5.   render() {  
  6.     return <Foo />;  
  7.   }  
  8. }  
  9.   
  10. class Foo extends React.Component {  
  11.   state = { count: 0 };  
  12.   
  13.   increment = () => {  
  14.     const { count } = this.state;  
  15.   
  16.     const newCount = count < 10 ? count + 1 : count;  
  17.   
  18.     this.setState({ count: newCount });  
  19.   };  
  20.   
  21.   render() {  
  22.     const { count } = this.state;  
  23.     console.log("Foo render");  
  24.   
  25.     return (  
  26.       <div>  
  27.         <h1> {count} </h1>  
  28.         <button onClick={this.increment}>Increment</button>  
  29.       </div>  
  30.     );  
  31.   }  
  32. }  
  33.   
  34. const rootElement = document.getElementById("root");  
  35. ReactDOM.render(<App />, rootElement);  

可以看到,代碼中的邏輯是我們點(diǎn)擊就會(huì)更新 count,到 10 以后,就會(huì)維持在 10。增加一個(gè) console.log,這樣我們就可以知道 render 是否被調(diào)用了。從執(zhí)行結(jié)果可以知道,即使 count 到了 10 以上,render 仍然會(huì)被調(diào)用。

總結(jié):繼承了 React.Component 的 class 組件,即使?fàn)顟B(tài)沒(méi)變化,只要調(diào)用了setState 就會(huì)觸發(fā) render。

b. 函數(shù)式組件更新?tīng)顟B(tài)時(shí)

我們用函數(shù)實(shí)現(xiàn)相同的組件,當(dāng)然因?yàn)橐袪顟B(tài),我們用上了 useState hook:

  1. import React, { useState } from "react";  
  2. import ReactDOM from "react-dom";  
  3.   
  4. class App extends React.Component {  
  5.   render() {  
  6.     return <Foo />;  
  7.   }  
  8. }  
  9.   
  10. function Foo() {  
  11.   const [count, setCount] = useState(0);  
  12.   
  13.   function increment() {  
  14.     const newCount = count < 10 ? count + 1 : count;  
  15.     setCount(newCount);  
  16.   }  
  17.   
  18.   console.log("Foo render");  
  19.     
  20.   return (  
  21.     <div>  
  22.       <h1> {count} </h1>  
  23.       <button onClick={increment}>Increment</button>  
  24.     </div>  
  25.   );  
  26. }  
  27.   
  28. const rootElement = document.getElementById("root");  
  29. ReactDOM.render(<App />, rootElement);  

我們可以注意到,當(dāng)狀態(tài)值不再改變之后,render 的調(diào)用就停止了。

總結(jié):對(duì)函數(shù)式組件來(lái)說(shuō),狀態(tài)值改變時(shí)才會(huì)觸發(fā) render 函數(shù)的調(diào)用。

2. 父容器重新渲染時(shí)

  1. import React from "react";  
  2. import ReactDOM from "react-dom";  
  3.   
  4. class App extends React.Component {  
  5.   state = { name: "App" };  
  6.   render() {  
  7.     return (  
  8.       <div className="App">  
  9.         <Foo />  
  10.         <button onClick={() => this.setState({ name: "App" })}>  
  11.           Change name  
  12.         </button>  
  13.       </div>  
  14.     );  
  15.   }  
  16. }  
  17.   
  18. function Foo() {  
  19.   console.log("Foo render");  
  20.   
  21.   return (  
  22.     <div>  
  23.       <h1> Foo </h1>  
  24.     </div>  
  25.   );  
  26. }  
  27.   
  28. const rootElement = document.getElementById("root");  
  29. ReactDOM.render(<App />, rootElement);  

只要點(diǎn)擊了 App 組件內(nèi)的 Change name 按鈕,就會(huì)重新 render。而且可以注意到,不管 Foo 具體實(shí)現(xiàn)是什么,F(xiàn)oo 都會(huì)被重新渲染。

總結(jié):無(wú)論組件是繼承自 React.Component 的 class 組件還是函數(shù)式組件,一旦父容器重新 render,組件的 render 都會(huì)再次被調(diào)用。

在「render」過(guò)程中會(huì)發(fā)生什么?

只要 render 函數(shù)被調(diào)用,就會(huì)有兩個(gè)步驟按順序執(zhí)行。這兩個(gè)步驟非常重要,理解了它們才好知道如何去優(yōu)化 React App。

Diffing

在此步驟中,React 將新調(diào)用的 render 函數(shù)返回的樹(shù)與舊版本的樹(shù)進(jìn)行比較,這一步是 React 決定如何更新 DOM 的必要步驟。雖然 React 使用高度優(yōu)化的算法執(zhí)行此步驟,但仍然有一定的性能開(kāi)銷(xiāo)。

Reconciliation

基于 diffing 的結(jié)果,React 更新 DOM 樹(shù)。這一步因?yàn)樾枰遁d和掛載 DOM 節(jié)點(diǎn)同樣存在許多性能開(kāi)銷(xiāo)。

開(kāi)始我們的 Tips

Tip #1:謹(jǐn)慎分配 state 以避免不必要的 render 調(diào)用

我們以下面為例,其中 App 會(huì)渲染兩個(gè)組件:

  1. CounterLabel  
  2. List  
  1. import React, { useState } from "react";  
  2. import ReactDOM from "react-dom";  
  3.   
  4. const ITEMS = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];  
  5.   
  6. function App() {  
  7.   const [count, setCount] = useState(0);  
  8.   const [items, setItems] = useState(ITEMS);  
  9.   return (  
  10.     <div className="App">  
  11.       <CounterLabel count={count} increment={() => setCount(count + 1)} />  
  12.       <List items={items} />  
  13.     </div>  
  14.   );  
  15. }  
  16.   
  17. function CounterLabel({ count, increment }) {  
  18.   return (  
  19.     <>  
  20.       <h1>{count} </h1>  
  21.       <button onClick={increment}> Increment </button>  
  22.     </>  
  23.   );  
  24. }  
  25.   
  26. function List({ items }) {  
  27.   console.log("List render");  
  28.   
  29.   return (  
  30.     <ul>  
  31.       {items.map((item, index) => (  
  32.         <li key={index}>{item} </li>  
  33.       ))}  
  34.     </ul>  
  35.   );  
  36. }  
  37.   
  38. const rootElement = document.getElementById("root");  
  39. ReactDOM.render(<App />, rootElement);  

執(zhí)行上面代碼可知,只要父組件 App 中的狀態(tài)被更新, CounterLabel 和 List 就都會(huì)更新。

當(dāng)然, CounterLabel 重新渲染是正常的,因?yàn)?count 發(fā)生了變化,自然要重新渲染;但是對(duì)于 List 而言,就完全是不必要的更新了,因?yàn)樗匿秩九c count 無(wú)關(guān)。 盡管 React 并不會(huì)在 reconciliation 階段真的更新 DOM,畢竟完全沒(méi)變化,但是仍然會(huì)執(zhí)行 diffing 階段來(lái)對(duì)前后的樹(shù)進(jìn)行對(duì)比,這仍然存在性能開(kāi)銷(xiāo)。

還記得 render 執(zhí)行過(guò)程中的 diffing 和 reconciliation 階段嗎?前面講過(guò)的東西在這里碰到了。

因此,為了避免不必要的 diffing 開(kāi)銷(xiāo),我們應(yīng)當(dāng)考慮將特定的狀態(tài)值放到更低的層級(jí)或組件中(與 React 中所說(shuō)的「提升」概念剛好相反)。在這個(gè)例子中,我們可以通過(guò)將 count 放到 CounterLabel 組件中管理來(lái)解決這個(gè)問(wèn)題。

Tip #2:合并狀態(tài)更新

因?yàn)槊看螤顟B(tài)更新都會(huì)觸發(fā)新的 render 調(diào)用,那么更少的狀態(tài)更新也就可以更少的調(diào)用 render 了。

我們知道,React class 組件有 componentDidUpdate(prevProps, prevState) 的鉤子,可以用來(lái)檢測(cè) props 或 state 有沒(méi)有發(fā)生變化。盡管有時(shí)有必要在 props 發(fā)生變化時(shí)再觸發(fā) state 更新,但我們總可以避免在一次 state 變化后再進(jìn)行一次 state 更新這種操作:

  1. import React from "react";  
  2. import ReactDOM from "react-dom";  
  3.   
  4. function getRange(limit) {  
  5.   let range = [];  
  6.   
  7.   for (let i = 0; i < limit; i++) {  
  8.     range.push(i);  
  9.   }  
  10.   
  11.   return range;  
  12. }  
  13.   
  14. class App extends React.Component {  
  15.   state = {  
  16.     numbers: getRange(7),  
  17.     limit: 7  
  18.   };  
  19.   
  20.   handleLimitChange = e => {  
  21.     const limit = e.target.value;  
  22.     const limitChanged = limit !== this.state.limit;  
  23.   
  24.     if (limitChanged) {  
  25.       this.setState({ limit });  
  26.     }  
  27.   };  
  28.   
  29.   componentDidUpdate(prevProps, prevState) {  
  30.     const limitChanged = prevState.limit !== this.state.limit;  
  31.     if (limitChanged) {  
  32.       this.setState({ numbers: getRange(this.state.limit) });  
  33.     }  
  34.   }  
  35.   
  36.   render() {  
  37.     return (  
  38.       <div>  
  39.         <input  
  40.           onChange={this.handleLimitChange}  
  41.           placeholder="limit"  
  42.           value={this.state.limit}  
  43.         />  
  44.         {this.state.numbers.map((number, idx) => (  
  45.           <p key={idx}>{number} </p>  
  46.         ))}  
  47.       </div>  
  48.     );  
  49.   }  
  50. }  
  51.   
  52. const rootElement = document.getElementById("root");  
  53. ReactDOM.render(<App />, rootElement);  

這里渲染了一個(gè)范圍數(shù)字序列,即范圍為 0 到 limit。只要用戶改變了 limit 值,我們就會(huì)在 componentDidUpdate 中進(jìn)行檢測(cè),并設(shè)定新的數(shù)字列表。

毫無(wú)疑問(wèn),上面的代碼是可以滿足需求的,但是,我們?nèi)匀豢梢赃M(jìn)行優(yōu)化。

上面的代碼中,每次 limit 發(fā)生改變,我們都會(huì)觸發(fā)兩次狀態(tài)更新:***次是為了修改 limit,第二次是為了修改展示的數(shù)字列表。這樣一來(lái),每次 limit 的變化會(huì)帶來(lái)兩次 render 開(kāi)銷(xiāo):

  1. // 初始狀態(tài)  
  2. { limit: 7, numbers: [0, 1, 2, 3, 4, 5, 6]  
  3. // 更新 limit -> 4  
  4. render 1: { limit: 4, numbers: [0, 1, 2, 3, 4, 5, 6] } //   
  5. render 2: { limit: 4, numbers: [0, 2, 3]  

我們的代碼邏輯帶來(lái)了下面的問(wèn)題:

  • 我們觸發(fā)了比實(shí)際需要更多的狀態(tài)更新;
  • 我們出現(xiàn)了「不連續(xù)」的渲染結(jié)果,即數(shù)字列表與 limit 不匹配。

為了改進(jìn),我們應(yīng)避免在不同的狀態(tài)更新中改變數(shù)字列表。事實(shí)上,我們可以在一次狀態(tài)更新中搞定:

  1. import React from "react";  
  2. import ReactDOM from "react-dom";  
  3.   
  4. function getRange(limit) {  
  5.   let range = [];  
  6.   
  7.   for (let i = 0; i < limit; i++) {  
  8.     range.push(i);  
  9.   }  
  10.   
  11.   return range;  
  12. }  
  13.   
  14. class App extends React.Component {  
  15.   state = {  
  16.     numbers: [1, 2, 3, 4, 5, 6],  
  17.     limit: 7  
  18.   };  
  19.   
  20.   handleLimitChange = e => {  
  21.     const limit = e.target.value;  
  22.     const limitChanged = limit !== this.state.limit;  
  23.     if (limitChanged) {  
  24.       this.setState({ limit, numbers: getRange(limit) });  
  25.     }  
  26.   };  
  27.   
  28.   render() {  
  29.     return (  
  30.       <div>  
  31.         <input  
  32.           onChange={this.handleLimitChange}  
  33.           placeholder="limit"  
  34.           value={this.state.limit}  
  35.         />  
  36.         {this.state.numbers.map((number, idx) => (  
  37.           <p key={idx}>{number} </p>  
  38.         ))}  
  39.       </div>  
  40.     );  
  41.   }  
  42. }  
  43.   
  44. const rootElement = document.getElementById("root");  
  45. ReactDOM.render(<App />, rootElement);  

Tip #3:使用 PureComponent 和 React.memo 以避免不必要的 render 調(diào)用

我們?cè)谥暗睦又锌吹綄⑻囟顟B(tài)值放到更低的層級(jí)來(lái)避免不必要渲染的方法,不過(guò)這并不總是有用。

我們來(lái)看下下面的例子:

  1. import React, { useState } from "react";  
  2. import ReactDOM from "react-dom";  
  3.   
  4. function App() {  
  5.   const [isFooVisible, setFooVisibility] = useState(false);  
  6.   
  7.   return (  
  8.     <div className="App">  
  9.       {isFooVisible ? (  
  10.         <Foo hideFoo={() => setFooVisibility(false)} />  
  11.       ) : (  
  12.         <button onClick={() => setFooVisibility(true)}>Show Foo </button>  
  13.       )}  
  14.       <Bar name="Bar" />  
  15.     </div>  
  16.   );  
  17. }  
  18.   
  19. function Foo({ hideFoo }) {  
  20.   return (  
  21.     <>  
  22.       <h1>Foo</h1>  
  23.       <button onClick={hideFoo}>Hide Foo</button>  
  24.     </>  
  25.   );  
  26. }  
  27.   
  28. function Bar({ name }) {  
  29.   return <h1>{name}</h1>;  
  30. }  
  31.   
  32. const rootElement = document.getElementById("root");  
  33. ReactDOM.render(<App />, rootElement);  

可以看到,只要父組件 App 的狀態(tài)值 isFooVisible 發(fā)生變化,F(xiàn)oo 和 Bar 就都會(huì)被重新渲染。

這里因?yàn)闉榱藳Q定 Foo 是否要被渲染出來(lái),我們需要將 isFooVisible 放在 App中維護(hù),因此也就不能將狀態(tài)拆出放到更低的層級(jí)。不過(guò),在 isFooVisible 發(fā)生變化時(shí)重新渲染 Bar 仍然是不必要的,因?yàn)?Bar 并不依賴 isFooVisible。我們只希望 Bar 在傳入屬性 name 變化時(shí)重新渲染。

那我們?cè)撛趺锤隳兀績(jī)煞N方法。

其一,對(duì) Bar 做記憶化(memoize):

  1. const Bar = React.memo(function Bar({name}) {  
  2.   return <h1>{name}</h1>;  
  3. });  

這就能保證 Bar 只在 name 發(fā)生變化時(shí)才重新渲染。

此外,另一個(gè)方法就是讓 Bar 繼承 React.PureComponent 而非 React.Component:

  1. class Bar extends React.PureComponent {  
  2.  render() {  
  3.    return <h1>{name}</h1>;  
  4.  }  
  5. }  

是不是很熟悉?我們經(jīng)常提到使用 React.PureComponent 能帶來(lái)一定的性能提升,避免不必要的 render。

總結(jié):避免組件不必要的渲染的方法有:React.memo 包裹的函數(shù)式組件,繼承自 React.PureComponent 的 class 組件。

為什么不讓每個(gè)組件都繼承 PureComponent 或者用 memo 包呢?

如果這條建議可以讓我們避免不必要的重新渲染,那我們?yōu)槭裁床话衙總€(gè) class 組件變成 PureComponent、把每個(gè)函數(shù)式組件用 React.memo 包起來(lái)?為什么有了更好的方法還要保留 React.Component 呢?為什么函數(shù)式組件不默認(rèn)記憶化呢?

毫無(wú)疑問(wèn),這些方法并不總是萬(wàn)靈藥。

嵌套對(duì)象的問(wèn)題

我們先來(lái)考慮下 PureComponent 和 React.memo 的組件到底做了什么?

每次更新的時(shí)候(包括狀態(tài)更新或上層組件重新渲染),它們就會(huì)在新 props、state 和舊 props、state 之間對(duì) key 和 value 進(jìn)行淺比較。淺比較是個(gè)嚴(yán)格相等的檢查,如果檢測(cè)到差異,render 就會(huì)執(zhí)行:

  1. // 基本類(lèi)型的比較  
  2. shallowCompare({ name: 'bar'}, { name: 'bar'}); // output: true  
  3. shallowCompare({ name: 'bar'}, { name: 'bar1'}); // output: false  

盡管基本類(lèi)型(如字符串、數(shù)字、布爾)的比較可以工作的很好,但對(duì)象這類(lèi)復(fù)雜的情況可能就會(huì)帶來(lái)意想不到的行為:

  1. shallowCompare({ name: {first: 'John', last: 'Schilling'}},  
  2.                { name: {first: 'John', last: 'Schilling'}}); // output: false  

上述兩個(gè) name 對(duì)應(yīng)的對(duì)象的引用是不同的。

我們重新看下之前的例子,然后修改我們傳入 Bar 的 props:

  1. import React, { useState } from "react";  
  2. import ReactDOM from "react-dom";  
  3.   
  4. const Bar = React.memo(function Bar({ name: { first, last } }) {  
  5.   console.log("Bar render");  
  6.   
  7.   return (  
  8.     <h1>  
  9.       {first} {last}  
  10.     </h1>  
  11.   );  
  12. });  
  13.   
  14. function Foo({ hideFoo }) {  
  15.   return (  
  16.     <>  
  17.       <h1>Foo</h1>  
  18.       <button onClick={hideFoo}>Hide Foo</button>  
  19.     </>  
  20.   );  
  21. }  
  22.   
  23. function App() {  
  24.   const [isFooVisible, setFooVisibility] = useState(false);  
  25.   
  26.   return (  
  27.     <div className="App">  
  28.       {isFooVisible ? (  
  29.         <Foo hideFoo={() => setFooVisibility(false)} />  
  30.       ) : (  
  31.         <button onClick={() => setFooVisibility(true)}>Show Foo</button>  
  32.       )}  
  33.       <Bar name={{ first: "John", last: "Schilling" }} />  
  34.     </div>  
  35.   );  
  36. }  
  37.   
  38. const rootElement = document.getElementById("root");  
  39. ReactDOM.render(<App />, rootElement);  

盡管 Bar 做了記憶化且 props 值并沒(méi)有發(fā)生變動(dòng),每次父組件重新渲染時(shí)它仍然會(huì)重新渲染。這是因?yàn)楸M管每次比較的兩個(gè)對(duì)象擁有相同的值,引用并不同。

函數(shù) props 的問(wèn)題

我們也可以把函數(shù)作為 props 向組件傳遞,當(dāng)然,在 JavaScript 中函數(shù)也會(huì)傳遞引用,因此淺比較也是基于其傳遞的引用。

因此,如果我們傳遞的是箭頭函數(shù)(匿名函數(shù)),組件仍然會(huì)在父組件重新渲染時(shí)重新渲染。

Tip #4:更好的 props 寫(xiě)法

前面的問(wèn)題的一種解決方法是改寫(xiě)我們的 props。

我們不傳遞對(duì)象作為 props,而是 將對(duì)象拆分成基本類(lèi)型 :

  1. <Bar firstName="John" lastName="Schilling" />  

而對(duì)于傳遞箭頭函數(shù)的場(chǎng)景,我們可以代以只***聲明過(guò)一次的函數(shù),從而總可以拿到相同的引用,如下所示:

  1. class App extends React.Component{  
  2.   constructor(props) {  
  3.     this.doSomethingMethod = this.doSomethingMethod.bind(this);      
  4.   }  
  5.   doSomethingMethod () { // do something}  
  6.     
  7.   render() {  
  8.     return <Bar onSomething={this.doSomethingMethod} />  
  9.   }  
  10. }  

Tip #5:控制更新

還是那句話,任何方法總有其適用范圍。

第三條建議雖然處理了不必要的更新問(wèn)題,但我們也不總能使用它。

而第四條,在某些情況下我們并不能拆分對(duì)象,如果我們傳遞了某種嵌套確實(shí)復(fù)雜的數(shù)據(jù)結(jié)構(gòu),那我們也很難將其拆分開(kāi)來(lái)。

不僅如此,我們也不總能傳遞只聲明了一次的函數(shù)。比如在我們的例子中,如果 App 是個(gè)函數(shù)式組件,恐怕就不能做到這一點(diǎn)了(在 class 組件中,我們可以用 bind 或者類(lèi)內(nèi)箭頭函數(shù)來(lái)保證 this 的指向及***聲明,而在函數(shù)式組件中則可能會(huì)有些問(wèn)題)。

幸運(yùn)的是, 無(wú)論是 class 組件還是函數(shù)式組件,我們都有辦法控制淺比較的邏輯 。

在 class 組件中,我們可以使用生命周期鉤子 shouldComponentUpdate(prevProps, prevState)來(lái)返回一個(gè)布爾值,當(dāng)返回值為 true 時(shí)才會(huì)觸發(fā) render。

而如果我們使用 React.memo,我們可以傳遞一個(gè)比較函數(shù)作為第二個(gè)參數(shù)。

注意! React.memo 的第二參數(shù)(比較函數(shù))和 shouldComponentUpdate 的邏輯是相反的,只有當(dāng)返回值為 false 的時(shí)候才會(huì)觸發(fā) render。 參考文檔 。

  1. const Bar = React.memo(  
  2.   function Bar({ name: { first, last } }) {  
  3.     console.log("update");  
  4.     return (  
  5.       <h1>  
  6.         {first} {last}  
  7.       </h1>  
  8.     );  
  9.   },  
  10.   (prevProps, newProps) =>  
  11.     prevProps.name.first === newProps.name.first &&  
  12.     prevProps.name.last === newProps.name.last  
  13. );  

盡管這條建議是可行的,但我們?nèi)砸⒁?nbsp;比較函數(shù)的性能開(kāi)銷(xiāo) 。如果 props 對(duì)象過(guò)深,反而會(huì)消耗不少的性能。

總結(jié)

上述場(chǎng)景仍不夠全面,但多少能帶來(lái)一些啟發(fā)性思考。當(dāng)然在性能方面,我們還有許多其他的問(wèn)題需要考慮,但遵守上述的準(zhǔn)則仍能帶來(lái)相當(dāng)不錯(cuò)的性能提升。

責(zé)任編輯:張燕妮 來(lái)源: segmentfault.com
相關(guān)推薦

2021-08-27 14:26:06

開(kāi)發(fā)技能React

2016-12-19 10:00:00

React性能優(yōu)化

2021-06-17 08:59:45

React前端優(yōu)化

2018-11-20 10:50:00

Java性能優(yōu)化編程技巧

2010-04-21 12:49:57

Oracle性能

2009-06-16 16:39:49

Hibernate性能

2013-06-08 14:19:05

性能優(yōu)化KVM

2011-07-11 15:26:49

性能優(yōu)化算法

2019-08-21 10:53:29

.NET性能優(yōu)化

2023-11-01 17:57:56

React應(yīng)用程序性能

2012-07-23 10:22:15

Python性能優(yōu)化優(yōu)化技巧

2009-12-09 17:33:22

PHP性能優(yōu)化

2022-08-03 09:11:31

React性能優(yōu)化

2022-05-23 13:44:53

前端開(kāi)發(fā)優(yōu)化

2012-09-11 15:43:32

HBase

2011-06-14 14:17:23

性能優(yōu)化系統(tǒng)層次

2015-09-15 08:30:23

Android代碼優(yōu)化

2011-06-14 14:32:46

性能優(yōu)化

2011-06-14 11:14:10

性能優(yōu)化代碼

2024-10-09 23:32:50

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)