發(fā)布于:2021-02-04 11:15:20
0
188
0
在許多情況下,React組件將在不必重新渲染時(shí)重新渲染。
如果渲染的結(jié)果與組件上一次渲染的結(jié)果完全相同,則最好完全跳過(guò)該渲染(協(xié)調(diào))步驟。
基于類(lèi)的組件
shouldComponentUpdate
在類(lèi)組件中,方法shouldComponentUpdate
允許這樣做。
它是在render()
之前調(diào)用的生命周期方法。該方法返回一個(gè)布爾值。如果render()
可以跳過(guò),這個(gè)布爾值告訴React。
當(dāng)true
時(shí),render()
將像平常一樣執(zhí)行。
當(dāng)false
時(shí),告訴React它可以跳過(guò)執(zhí)行render()
。
用下一個(gè)道具和下一個(gè)狀態(tài)調(diào)用 默認(rèn)情況下, 完全不指定此方法。 shouldComponentUpdate(nextProps, nextState) { 不要依賴(lài)于此來(lái)完全阻止渲染。它現(xiàn)在可能工作,但它可能會(huì)導(dǎo)致錯(cuò)誤,并可能在未來(lái)發(fā)生變化。相反,將其視為一個(gè)反應(yīng)提示,告訴它“您可以安全地跳過(guò)渲染,結(jié)果將與上一個(gè)結(jié)果相同”。 在您知道之前,該方法看起來(lái)會(huì)是這樣的。 shouldComponentUpdate(nextProps, nextState) { 我只是想看看有沒(méi)有什么道具或者狀態(tài)改變了,為什么這么難? 這會(huì)減少跳過(guò)必要更新的可能性(例如,添加新道具時(shí))。 除非您確信需要自定義道具,否則最好選擇 這意味著這兩個(gè)片段是等價(jià)的。 class Driver extends React.Component { 當(dāng)試圖將同樣的優(yōu)化應(yīng)用于函數(shù)組件而不是基于類(lèi)的組件時(shí),問(wèn)題就出現(xiàn)了。函數(shù)組件不能真正跳過(guò)渲染步驟。函數(shù)組件(實(shí)際上只是一個(gè)函數(shù))要么執(zhí)行要么不執(zhí)行 這就是備忘錄有幫助的地方。 備忘錄基本上是一種技術(shù),用于以后記住一些東西。 React不能只記住數(shù)據(jù)片段,它可以記住整個(gè)組件。 前兩個(gè)示例是針對(duì)基于類(lèi)的組件的, 不像在基于類(lèi)的組件中那樣跳過(guò)渲染步驟, // the function component 帶有道具的記憶驅(qū)動(dòng)程序組件的初始呈現(xiàn) 函數(shù)組件render <p>Charles Leclerc</p>。 道具更改為 組件渲染 <p>Daniel Ricciardo</p> 觸發(fā)驅(qū)動(dòng)程序更新的其他更改組件 React使用前面的結(jié)果而不是計(jì)算渲染結(jié)果:<p>Daniel Ricciardo</p> 默認(rèn)情況下, 比較函數(shù)還返回一個(gè)布爾值。 該布爾值告訴React它是否應(yīng)該使用組件的前一個(gè)結(jié)果,而不是計(jì)算新的結(jié)果。 當(dāng) 當(dāng) 小心!這與 使用上一個(gè)道具和下一個(gè)道具調(diào)用比較函數(shù)。這允許復(fù)雜的邏輯,將當(dāng)前道具與以前的道具進(jìn)行比較,以確定輸出是否不同,因此應(yīng)使用組件的記憶結(jié)果/備忘錄。 // the function component 要使用基于類(lèi)的組件擴(kuò)展并行程序: 除非您確信需要自定義比較函數(shù),否則最好使用默認(rèn)行為。 示例 在這個(gè)演示中,有一個(gè)頂級(jí)組件有兩個(gè)狀態(tài),一個(gè)是 您可以通過(guò)按鈕增加 頂部組件有4個(gè)子組件,所有子組件都將顯示 只有在更新 而 const memoizedValue = React.useMemo(() => computeExpensiveValue(a, b), [a, b]); 告訴 傳遞的函數(shù)中使用的每個(gè)值都應(yīng)包含在依賴(lài)項(xiàng)數(shù)組中。 這將防止許多意外行為。 React團(tuán)隊(duì)創(chuàng)建了一個(gè)ESLint包, 示例 import React from 'react'; 使用props的驅(qū)動(dòng)程序組件的初始呈現(xiàn) 函數(shù)組件計(jì)算 props更改為 React.useMemo看不到依賴(lài)項(xiàng)數(shù)組中的任何內(nèi)容已更改,并且不會(huì)重新計(jì)算numOfPodiums 使用 道具再次更改為 React.useMemo 看到依賴(lài)項(xiàng)數(shù)組中發(fā)生了一些變化并計(jì)算 numOfPodiums 并使用新計(jì)算的值。 這是特定 但值完全可以是函數(shù)! 這意味著這兩個(gè)片段是等價(jià)。 const memoizedFunction = React.useMemo(function() { 這將記憶第一個(gè)參數(shù)(函數(shù))返回的值,該值是一個(gè)名為 const memoizedFunction = React.useCallback(function doTheThing(a, b) { 這將記憶第一個(gè)參數(shù),這是一個(gè)名為 與 函數(shù)shouldComponentUpdate()
。這允許復(fù)雜的邏輯,將當(dāng)前的屬性/狀態(tài)與以前的屬性/狀態(tài)進(jìn)行比較,以確定輸出是否不同,因此組件應(yīng)該更新。shouldComponentUpdate()
返回true。
return true
}shouldComponentUpdate
中的邏輯很快就會(huì)變得非常復(fù)雜,并且容易出錯(cuò)。
const propsComparison = this.props.a !== nextProps.a && this.props.b !== nextProps.b && this.props.c !== nextProps.c && this.props.d !== nextProps.d
const stateComparison = this.state.one !== nextState.one && this.state.two !== nextState.two && this.state.three !== nextState.three
return propsComparison && stateComparison
}React.PureComponent
React.PureComponent
就是這樣!PureComponent
執(zhí)行道具和狀態(tài)的淺表比較(通過(guò)使用Object.is)。PureComponent
。
shouldComponentUpdate() {
// a shallow comparison of all the props and state
}
render() {{this.props.name};
}
}class Driver extends React.PureComponent { render() {{this.props.name}; } }
功能部件
React.memo
React.memo
這樣做!React.memo
是針對(duì)函數(shù)組件的。React.memo
將重用上次渲染的結(jié)果,而不是計(jì)算新結(jié)果。
const Driver = function(props) {
return{props.name};
};
// exporting the memoized function component
export default React.memo(Driver);{ name: "Charles Leclerc" }
{ name: "Daniel Ricciardo" }
React.memo
看到道具沒(méi)有更改。React.memo
與React.PureComponent
相當(dāng),因?yàn)樗鼘?duì)所有道具進(jìn)行了淺層比較(使用對(duì)象.is如果您想獲得更多的控制權(quán)并負(fù)責(zé)比較,React.memo
接受第二個(gè)參數(shù),即比較函數(shù)。這使得它在基于類(lèi)的組件中與shouldComponentUpdate
相當(dāng)。false
時(shí),函數(shù)組件將像平常一樣執(zhí)行。true
時(shí),函數(shù)組件將不執(zhí)行,并且將使用前面的結(jié)果。shouldComponentUpdate
相反!
const Driver = function(props) {
return{props.name};
};
// the custom comparison function
const comparisonFn = function(prevProps, nextProps) {
return prevProps.name === nextProps.name;
};
// exporting the memoized function component
export default React.memo(Driver, comparisonFn);count
和一個(gè)是unusedCount
。顧名思義,它仍將被閑置。count
和unusedCount。
count
以及該子組件渲染的次數(shù)。count
時(shí),具有上述優(yōu)化之一的組件才會(huì)渲染。當(dāng)更新unusedCount
時(shí),其他的也會(huì)渲染。React.memo
與React.useMemo
React.memo
是一個(gè)高階組件,因?yàn)樗邮芤粋€(gè)組件并返回新的/記憶的組件。React.useMemo
是一個(gè)hook(它是一個(gè)函數(shù))。它接受一個(gè)函數(shù)并返回所傳遞函數(shù)的記憶返回值。React.useMemo
React.useMemo
接受函數(shù)作為第一個(gè)參數(shù)。此函數(shù)返回的值是React.useMemo
將返回的值。只有在必要時(shí)才會(huì)重新計(jì)算。React.useMemo
將返回已記憶/已記憶的值(如果沒(méi)有)。React.useMemo
是否應(yīng)該通過(guò)第二個(gè)參數(shù)(數(shù)組)重新計(jì)算結(jié)果。傳遞的函數(shù)返回的值只有在依賴(lài)項(xiàng)數(shù)組中的某些內(nèi)容發(fā)生更改時(shí)才會(huì)再次計(jì)算。不傳遞任何內(nèi)容將導(dǎo)致每次呈現(xiàn)組件時(shí)都計(jì)算該值(并導(dǎo)致函數(shù)運(yùn)行)。eslint-plugin-react-hooks
,用于在違反hook規(guī)則時(shí)發(fā)出警告。正在完成的依賴(lài)關(guān)系數(shù)組由該包中名為exhaustive-deps
的規(guī)則檢查。
function calculatePodiums(name) {
// very expensive calculation
return numResult;
}
const Driver = function(props) {
const numOfPodiums = React.useMemo(() => calculatePodiums(props.name), [
props.name
]);
return (My name is: {props.name}I drive for: {props.team}I have been on the podium {numOfPodiums} times);
};{ name: "Kimi R?ikk?nen", team: "Ferrari" }
numOfPodiums
并使用該計(jì)算的結(jié)果進(jìn)行呈現(xiàn)。{ name: "Kimi R?ikk?nen", team: "Alfa Romeo Racing" }
numOfPodiums
的memo/membered值。{ name: "Antonio Giovinazzi", team: "Alfa Romeo Racing" }
React.useCallback
React.useMemo
用法的快捷方式。React.useMemo
返回已記憶的值.React.useCallback
返回已記憶的函數(shù).
return function doTheThing(a, b) {
// do the thing
}
}
}, [a, b])doTheThing。
// do the thing
}
}, [a, b])doTheThing
的函數(shù)。React.useMemo
一樣,第二個(gè)參數(shù)是一個(gè)依賴(lài)項(xiàng)數(shù)組。React.useCallback
僅當(dāng)該數(shù)組中的某些內(nèi)容發(fā)生更改時(shí)才會(huì)返回更改。
作者介紹
熱門(mén)博客推薦