React 基礎(chǔ)鞏固(二十三)——React 性能優(yōu)化 SCU
React 更新機(jī)制
-
React 的渲染流程
- JSX -> 虛擬 DOM -> 真實(shí) DOM
-
React 的更新流程
-
props/state 改變
->render函數(shù)重新執(zhí)行
->產(chǎn)生新的DOM樹
->新舊DOM樹進(jìn)行diff
->計(jì)算出差異進(jìn)行更新
->更新到真實(shí)的DOM
-
-
React 在 props 或 state 發(fā)生改變時(shí),會(huì)調(diào)用 React 的 render 方法,會(huì)創(chuàng)建一顆不同的樹
-
React 需要基于這兩顆不同的樹之間的差別來判斷如何有效的更新 UI
- 如果一顆樹參考另外一顆樹進(jìn)行完全比較更新,那么即使時(shí)最先進(jìn)的算法,該算法的復(fù)雜度為 O(n^2),其中 n 是樹中元素的數(shù)量;
- 如果在 React 中使用了該算法,那么展示 1000 個(gè)元素所需要執(zhí)行的計(jì)算量將在 10 億的量級(jí)范圍;
- 開銷過于昂貴,更新性能非常低效;
-
于是,React 對(duì)這個(gè)算法進(jìn)行了優(yōu)化,將其優(yōu)化成了 O(n)
- 同層節(jié)點(diǎn)之間相互比較,不會(huì)跨節(jié)點(diǎn)比較
- 不同類型的節(jié)點(diǎn),產(chǎn)生不同的樹結(jié)構(gòu)
- 開發(fā)中,可以通過 key 來指定哪些節(jié)點(diǎn)在不同的渲染下保持穩(wěn)定
-
keys 的優(yōu)化
- 遍歷列表時(shí),會(huì)提示一個(gè)警告,提示我們加入一個(gè) key 屬性
- 當(dāng)子元素?fù)碛?key 時(shí),React 使用 key 來匹配原有樹上的子元素以及最新樹上的子元素
- 例如將 key 為 333 的元素插入到最前面的位置時(shí),key 為 111,222 的元素,僅僅需要進(jìn)行位移即可,不需要任何修改
-
key 的注意事項(xiàng)
- key 應(yīng)該是唯一的
- key 不要使用隨機(jī)數(shù)(隨機(jī)數(shù)在下一次 render 時(shí),會(huì)重新生成一個(gè)數(shù)字)
- 使用 index 作為 key,對(duì)性能是沒有優(yōu)化的
-
render 函數(shù)被調(diào)用
- 為了避免不必要的 render,提高性能,調(diào)用 render 應(yīng)該有一個(gè)前提:依賴的數(shù)據(jù)(state、props)發(fā)生改變時(shí),再調(diào)用 render 方法
-
利用
shouldComponentUpdate
優(yōu)化 render 調(diào)用
// 針對(duì)值發(fā)生變化的組件
shouldComponentUpdate(nextProps, newState){
// 對(duì)比 state中的值是否有改變
if (this.state.message !== newState.message || this.state.counter !== newState.counter){
return true
}
return false
}
// 針對(duì)其中的子組件
shouldComponentUpdate(nextProps, newState){
// 1.對(duì)比 state中的值是否有改變
if (this.state.message !== newState.message || this.state.counter !== newState.counter){
return true
}
// 2.檢測(cè)接收的props是否有改變
if (this.props.message !== newProps.message){
return true
}
return false
}
- 如果參數(shù)過多,SCU 的方式則過于繁瑣,所以通常采用以下方式實(shí)現(xiàn)
針對(duì)類組件:采用PureComponent 實(shí)現(xiàn)優(yōu)化
import React, { PureComponent } from "react";
export class App extends PureComponent {
// ...
}
PureComponent中變更數(shù)組數(shù)據(jù)的實(shí)際應(yīng)用:文章來源:http://www.zghlxwxcb.cn/news/detail-554828.html
import React, { PureComponent } from "react";
export class App extends PureComponent {
constructor() {
super();
this.state = {
books: [
{ name: "book1", price: 199, count: 1 },
{ name: "book2", price: 299, count: 1 },
{ name: "book3", price: 399, count: 2 },
{ name: "book4", price: 499, count: 3 },
{ name: "book5", price: 599, count: 1 },
],
};
}
addNewBook() {
const newBook = {
name: "book6",
price: 55,
count: 1,
};
// 錯(cuò)誤寫法:
// 直接修改原有的state,重新設(shè)置一遍
// this.state.books.push(newBook);
// this.setState({
// books: this.state.books,
// });
// 正確寫法:
// 拷貝一份,在新的數(shù)組中更新,設(shè)置新的books,而不是直接修改state
const books = [...this.state.books];
books.push(newBook);
this.setState({ books });
}
addBookCount(index) {
console.log(index);
const books = [...this.state.books];
books[index].count++;
this.setState({ books });
}
render() {
const { books } = this.state;
return (
<div>
<h2>books list</h2>
<ul>
{books.map((item, index) => {
return (
<li key={index}>
<span>
name: {item.name} - price: {item.price} - count: {item.count}
</span>
<button onClick={(e) => this.addBookCount(index)}>+1</button>
</li>
);
})}
</ul>
<button onClick={(e) => this.addNewBook()}>添加新書籍</button>
</div>
);
}
}
export default App;
針對(duì)函數(shù)式組件:采用 memo 實(shí)現(xiàn)優(yōu)化文章來源地址http://www.zghlxwxcb.cn/news/detail-554828.html
import { memo } from "react";
const Profile = memo(function (props) {
console.log("profile render");
return <h2>Profile: {props.message}</h2>;
});
export default Profile;
到了這里,關(guān)于【前端知識(shí)】React 基礎(chǔ)鞏固(二十三)——React 性能優(yōu)化 SCU相關(guān)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!