React?性能優(yōu)化方法總結(jié)
前言
要講清楚性能優(yōu)化的原理,就需要知道它的前世今生,需要回答如下的問題:
- React 是如何進(jìn)行頁面渲染的?
- 造成頁面的卡頓的罪魁禍?zhǔn)资鞘裁茨兀?/li>
- 我們?yōu)槭裁葱枰阅軆?yōu)化?
- React 有哪些場(chǎng)景會(huì)需要性能優(yōu)化?
- React 本身的性能優(yōu)化手段?
- 還有哪些工具可以提升性能呢?
為什么頁面會(huì)出現(xiàn)卡頓的現(xiàn)象?
為什么瀏覽器會(huì)出現(xiàn)頁面卡頓的問題?是不是瀏覽器不夠先進(jìn)?這都 2202 年了,怎么還會(huì)有這種問題呢?
實(shí)際上問題的根源來源于瀏覽器的刷新機(jī)制。
我們?nèi)祟愌劬Φ乃⑿侣适?60Hz,瀏覽器依據(jù)人眼的刷新率 計(jì)算出了
1000 Ms / 60 = 16.6ms
也就是說,瀏覽器要在16.6Ms 進(jìn)行一次刷新,人眼就不會(huì)感覺到卡頓,而如果超過這個(gè)時(shí)間進(jìn)行刷新,就會(huì)感覺到卡頓。
而瀏覽器的主進(jìn)程在僅僅需要頁面的渲染,還需要做解析執(zhí)行Js,他們運(yùn)行在一個(gè)進(jìn)程中。
如果js的在執(zhí)行的長時(shí)間占用主進(jìn)程的資源,就會(huì)導(dǎo)致沒有資源進(jìn)行頁面的渲染刷新,進(jìn)而導(dǎo)致頁面的卡頓。
那么這個(gè)又和 React 的性能優(yōu)化又有什么關(guān)系呢?
React 到底是在哪里出現(xiàn)了卡頓?
基于我們上的知識(shí),js 長期霸占瀏覽器主線程造成無法刷新而造成卡頓。
那么 React 的卡頓也是基于這個(gè)原因。
React 在render的時(shí)候,會(huì)根據(jù)現(xiàn)有render產(chǎn)生的新的jsx的數(shù)據(jù)和現(xiàn)有fiberRoot 進(jìn)行比對(duì),找到不同的地方,然后生成新的workInProgress,進(jìn)而在掛載階段把新的workInProgress交給服務(wù)器渲染。
在這個(gè)過程中,React 為了讓底層機(jī)制更高效快速,進(jìn)行了大量的優(yōu)化處理,如設(shè)立任務(wù)優(yōu)先級(jí)、異步調(diào)度、diff算法、時(shí)間分片等。
整個(gè)鏈路就是了高效快速的完成從數(shù)據(jù)更新到頁面渲染的整體流程。
為了不讓遞歸遍歷尋找所有更新節(jié)點(diǎn)太大而占用瀏覽器資源,React 升級(jí)了fiber架構(gòu),時(shí)間分片,讓其可以增量更新。
為了找出所有的更新節(jié)點(diǎn),設(shè)立了diff算法,高效的查找所有的節(jié)點(diǎn)。
為了更高效的更新,及時(shí)響應(yīng)用戶的操作,設(shè)計(jì)任務(wù)調(diào)度優(yōu)先級(jí)。
而我們的性能優(yōu)化就是為了不給 React 拖后腿,讓其更快,更高效的遍歷。
那么性能優(yōu)化的奧義是什么呢??
就是控制刷新渲染的波及范圍,我們只讓改更新的更新,不該更新的不要更新,讓我們的更新鏈路盡可能的短的走完,那么頁面當(dāng)然就會(huì)及時(shí)刷新不會(huì)卡頓了。
React 有哪些場(chǎng)景會(huì)需要性能優(yōu)化?
- 父組件刷新,而不波及子組件
- 組件自己控制自己是否刷新
- 減少波及范圍,無關(guān)刷新數(shù)據(jù)不存入state中
- 合并 state,減少重復(fù) setState 的操作
- 如何更快的完成diff的比較,加快進(jìn)程
我們分別從這些場(chǎng)景說一下:
一:父組件刷新,而不波及子組件。
我們知道 React 在組件刷新判定的時(shí)候,如果觸發(fā)刷新,那么它會(huì)深度遍歷所有子組件,查找所有更新的節(jié)點(diǎn),依據(jù)新的jsx數(shù)據(jù)和舊的 fiber ,生成新的workInProgress,進(jìn)而進(jìn)行頁面渲染。
所以父組件刷新的話,子組件必然會(huì)跟著刷新,但是假如這次的刷新,和我們子組件沒有關(guān)系呢?怎么減少這種波及呢?
如下面這樣:
export default function Father1 (){
let [name,setName] = React.useState('');
return (
<div>
<button onClick={()=>setName("獲取到的數(shù)據(jù)")}>點(diǎn)擊獲取數(shù)據(jù)</button>
{name}
<Children/>
</div>
)
}
function Children(){
return (
<div>
這里是子組件
</div>
)
}運(yùn)行結(jié)果:

可以看到我們的子組件被波及了,解決辦法有很多,總體來說分為兩種:
- 子組件自己判斷是否需要更新 ,典型的就是 PureComponent,shouldComponentUpdate,memo
- 父組件對(duì)子組件做個(gè)緩沖判斷
第一種:使用 PureComponent
使用 PureComponent 的原理就是它會(huì)對(duì)state 和props進(jìn)行淺比較,如果發(fā)現(xiàn)并不相同就會(huì)更新。
export default function Father1 (){
let [name,setName] = React.useState('');
return (
<div>
<button onClick={()=>setName("父組件的數(shù)據(jù)")}>點(diǎn)擊刷新父組件</button>
{name}
<Children1/>
</div>
)
}
class Children extends React.PureComponent{
render() {
return (
<div>這里是子組件</div>
)
}
}執(zhí)行結(jié)果:

實(shí)際上PureComponent就是在內(nèi)部更新的時(shí)候調(diào)用了會(huì)調(diào)用如下方法來判斷 新舊state和props
function shallowEqual(objA: mixed, objB: mixed): boolean {
if (is(objA, objB)) {
return true;
}
if (
typeof objA !== 'object' ||
objA === null ||
typeof objB !== 'object' ||
objB === null
) {
return false;
}
const keysA = Object.keys(objA);
const keysB = Object.keys(objB);
if (keysA.length !== keysB.length) {
return false;
}
// Test for A's keys different from B.
for (let i = 0; i < keysA.length; i++) {
const currentKey = keysA[i];
if (
!hasOwnProperty.call(objB, currentKey) ||
!is(objA[currentKey], objB[currentKey])
) {
return false;
}
}
return true;
}它的判斷步驟如下:
- 第一步,首先會(huì)直接比較新老
props或者新老state是否相等。如果相等那么不更新組件。 - 第二步,判斷新老
state或者props,有不是對(duì)象或者為null的,那么直接返回 false ,更新組件。 - 第三步,通過
Object.keys將新老props或者新老state的屬性名key變成數(shù)組,判斷數(shù)組的長度是否相等,如果不相等,證明有屬性增加或者減少,那么更新組件。 - 第四步,遍歷老
props或者老state,判斷對(duì)應(yīng)的新props或新state,有沒有與之對(duì)應(yīng)并且相等的(這個(gè)相等是淺比較),如果有一個(gè)不對(duì)應(yīng)或者不相等,那么直接返回false,更新組件。 到此為止,淺比較流程結(jié)束,PureComponent就是這么做渲染節(jié)流優(yōu)化的。
在使用PureComponent時(shí)需要注意的細(xì)節(jié);
由于PureComponent 使用的是淺比較判斷state和props,所以如果我們?cè)诟缸咏M件中,子組件使用PureComponent,在父組件刷新的過程中不小心把傳給子組件的回調(diào)函數(shù)變了,就會(huì)造成子組件的誤觸發(fā),這個(gè)時(shí)候PureComponent就失效了。
細(xì)節(jié)一:函數(shù)組件中,匿名函數(shù),箭頭函數(shù)和普通函數(shù)都會(huì)重新聲明
下面這些情況都會(huì)造成函數(shù)的重新聲明:
箭頭函數(shù)
<Children1 callback={(value)=>setValue(value)}/>匿名函數(shù)
<Children1 callback={function (value){setValue(value)}}/>普通函數(shù)
export default function Father1 (){
let [name,setName] = React.useState('');
let [value,setValue] = React.useState('')
const setData=(value)=>{
setValue(value)
}
return (
<div>
<button onClick={()=>setName("父組件的數(shù)據(jù)"+Math.random())}>點(diǎn)擊刷新父組件</button>
{name}
<Children1 callback={setData}/>
</div>
)
}
class Children1 extends React.PureComponent{
render() {
return (
<div>這里是子組件</div>
)
}
}執(zhí)行結(jié)果:

可以看到子組件的 PureComponent 完全失效了。這個(gè)時(shí)候就可以使用useMemo或者 useCallback 出馬了,利用他們緩沖一份函數(shù),保證不會(huì)出現(xiàn)重復(fù)聲明就可以了。
export default function Father1 (){
let [name,setName] = React.useState('');
let [value,setValue] = React.useState('')
const setData= React.useCallback((value)=>{
setValue(value)
},[])
return (
<div>
<button onClick={()=>setName("父組件的數(shù)據(jù)"+Math.random())}>點(diǎn)擊刷新父組件</button>
{name}
<Children1 callback={setData}/>
</div>
)
}看結(jié)果:

可以看到我們的子組件這次并沒有參與父組件的刷新,在React Profiler中也提示,Children1并沒有渲染。
細(xì)節(jié)二:class組件中不使用箭頭函數(shù),匿名函數(shù)
原理和函數(shù)組件中的一樣,class 組件中每一次刷新都會(huì)重復(fù)調(diào)用render函數(shù),那么render函數(shù)中使用的匿名函數(shù),箭頭函數(shù)就會(huì)造成重復(fù)刷新的問題。
export default class Father extends React.PureComponent{
constructor(props) {
super(props);
this.state = {
name:"",
count:"",
}
}
render() {
return (
<div>
<button onClick={()=>this.setState({name:"父組件的數(shù)據(jù)"+Math.random()})}>點(diǎn)擊獲取數(shù)據(jù)</button>
{this.state.name}
<Children1 callback={()=>this.setState({count:11})}/>
</div>
)
}
}執(zhí)行結(jié)果:

而優(yōu)化這個(gè)非常簡(jiǎn)單,只需要把函數(shù)換成普通函數(shù)就可以。
export default class Father extends React.PureComponent{
constructor(props) {
super(props);
this.state = {
name:"",
count:"",
}
}
setCount=(count)=>{
this.setState({count})
}
render() {
return (
<div>
<button onClick={()=>this.setState({name:"父組件的數(shù)據(jù)"+Math.random()})}>點(diǎn)擊獲取數(shù)據(jù)</button>
{this.state.name}
<Children1 callback={this.setCount(111)}/>
</div>
)
}
}執(zhí)行結(jié)果:

細(xì)節(jié)三:在 class 組件的render函數(shù)中bind 函數(shù)
這個(gè)細(xì)節(jié)是我們?cè)赾lass組件中,沒有在constructor中進(jìn)行bind的操作,而是在render函數(shù)中,那么由于bind函數(shù)的特性,它的每一次調(diào)用都會(huì)返回一個(gè)新的函數(shù),所以同樣會(huì)造成PureComponent的失效
export default class Father extends React.PureComponent{
//...
setCount(count){
this.setCount({count})
}
render() {
return (
<div>
<button onClick={()=>this.setState({name:"父組件的數(shù)據(jù)"+Math.random()})}>點(diǎn)擊獲取數(shù)據(jù)</button>
{this.state.name}
<Children1 callback={this.setCount.bind(this,"11111")}/>
</div>
)
}
}看執(zhí)行結(jié)果:

優(yōu)化的方式也很簡(jiǎn)單,把bind操作放在constructor中就可以了。
constructor(props) {
super(props);
this.state = {
name:"",
count:"",
}
this.setCount= this.setCount.bind(this);
}執(zhí)行結(jié)果就不在此展示了。
第二種:shouldComponentUpdate
class 組件中 使用 shouldComponentUpdate 是主要的優(yōu)化方式,它不僅僅可以判斷來自父組件的nextprops,還可以根據(jù)nextState和最新的nextContext來決定是否更新。
class Children2 extends React. PureComponent{
shouldComponentUpdate(nextProps, nextState, nextContext) {
//判斷只有偶數(shù)的時(shí)候,子組件才會(huì)更新
if(nextProps !== this.props && nextProps.count % 2 === 0){
return true;
}else{
return false;
}
}
render() {
return (
<div>
只有父組件傳入的值等于 2的時(shí)候才會(huì)更新
{this.props.count}
</div>
)
}
}它的用法也是非常簡(jiǎn)單,就是如果需要更新就返回true,不需要更新就返回false.
第三種:函數(shù)組件如何判斷props的變化的更新呢? 使用 React.memo函數(shù)
React.memo的規(guī)則是如果想要復(fù)用最后一次渲染結(jié)果,就返回true,不想復(fù)用就返回false。 所以它和shouldComponentUpdate的正好相反,false才會(huì)更新,true就返回緩沖。
const Children3 = React.memo(function ({count}){
return (
<div>
只有父組件傳入的值是偶數(shù)的時(shí)候才會(huì)更新
{count}
</div>
)
},(prevProps, nextProps)=>{
if(nextProps.count % 2 === 0){
return false;
}else{
return true;
}
})如果我們不傳入第二個(gè)函數(shù),而是默認(rèn)讓 React.memo包裹一下,那么它只會(huì)對(duì)props淺比較一下,并不會(huì)有比較state之類的邏輯。
以上三種都是我們?yōu)榱藨?yīng)對(duì)父組件更新觸發(fā)子組件,子組件決定是否更新的實(shí)現(xiàn)。 下面我們講一下父組件對(duì)子組件緩沖實(shí)現(xiàn)的情況:
使用 React.useMemo來實(shí)現(xiàn)對(duì)子組件的緩沖
看下面這段邏輯,我們的子組件只關(guān)心count數(shù)據(jù),當(dāng)我們刷新name數(shù)據(jù)的時(shí)候,并不會(huì)觸發(fā)刷新 Children1子組件,實(shí)現(xiàn)了我們對(duì)組件的緩沖控制。
export default function Father1 (){
let [count,setCount] = React.useState(0);
let [name,setName] = React.useState(0);
const render = React.useMemo(()=><Children1 count = {count}/>,[count])
return (
<div>
<button onClick={()=>setCount(++count)}>點(diǎn)擊刷新count</button>
<br/>
<button onClick={()=>setName(++name)}>點(diǎn)擊刷新name</button>
<br/>
{"count"+count}
<br/>
{"name"+name}
<br/>
{render}
</div>
)
}
class Children1 extends React.PureComponent{
render() {
return (
<div>
子組件只關(guān)系count 數(shù)據(jù)
{this.props.count}
</div>
)
}
}執(zhí)行結(jié)果: 當(dāng)我們點(diǎn)擊刷新name數(shù)據(jù)時(shí),可以看到?jīng)]有子組件參與刷新

當(dāng)我們點(diǎn)擊刷新count 數(shù)據(jù)時(shí),子組件參與了刷新

一:組件自己控制自己是否刷新
這里就需要用到上面提到的shouldComponentUpdate以及PureComponent,這里不再贅述。
三:減少波及范圍,無關(guān)刷新數(shù)據(jù)不存入state中
這種場(chǎng)景就是我們有意識(shí)的控制,如果有一個(gè)數(shù)據(jù)我們?cè)陧撁嫔喜]有用到它,但是它又和我們的其他的邏輯有關(guān)系,那么我們就可以把它存儲(chǔ)在其他的地方,而不是state中。
場(chǎng)景一:無意義重復(fù)調(diào)用setState,合并相關(guān)的state
export default class Father extends React.Component{
state = {
count:0,
name:"",
}
getData=(count)=>{
this.setState({count});
//依據(jù)異步獲取數(shù)據(jù)
setTimeout(()=>{
this.setState({
name:"異步獲取回來的數(shù)據(jù)"+count
})
},200)
}
componentDidUpdate(prevProps, prevState, snapshot) {
console.log("渲染次數(shù),",++count,"次")
}
render() {
return (
<div>
<button onClick={()=>this.getData(++this.state.count)}>點(diǎn)擊獲取數(shù)據(jù)</button>
{this.state.name}
</div>
)
}
}React Profiler的執(zhí)行結(jié)果:

可以看到我們的父組件執(zhí)行了兩次。 其中的一次是無意義的先setState保存一次數(shù)據(jù),然后又根據(jù)這個(gè)數(shù)據(jù)異步獲取了數(shù)據(jù)以后又調(diào)用了一次setState,造成了第二次的數(shù)據(jù)刷新.
而解決辦法就是把這個(gè)數(shù)據(jù)合并到異步數(shù)據(jù)獲取完成以后,一起更新到state中。
getData=(count)=>{
//依據(jù)異步獲取數(shù)據(jù)
setTimeout(()=>{
this.setState({
name:"異步獲取回來的數(shù)據(jù)"+count,
count
})
},200)
}看執(zhí)行結(jié)果:只渲染了一次。

場(chǎng)景二:和頁面刷新沒有相關(guān)的數(shù)據(jù),不存入state中
實(shí)際上我們發(fā)現(xiàn)這個(gè)數(shù)據(jù)在頁面上并沒有展示,我們并不需要把他們都存放在state 中,所以我們可以把這個(gè)數(shù)據(jù)存儲(chǔ)在state之外的地方。
export default class Father extends React.Component{
constructor(props) {
super(props);
this.state = {
name:"",
}
this.count = 0;
}
getData=(count)=>{
this.count = count;
//依據(jù)異步獲取數(shù)據(jù)
setTimeout(()=>{
this.setState({
name:"異步獲取回來的數(shù)據(jù)"+count,
})
},200)
}
componentDidUpdate(prevProps, prevState, snapshot) {
console.log("渲染次數(shù),",++count,"次")
}
render() {
return (
<div>
<button onClick={()=>this.getData(++this.count)}>點(diǎn)擊獲取數(shù)據(jù)</button>
{this.state.name}
</div>
)
}
}這樣的操作并不會(huì)影響我們對(duì)它的使用。 在class組件中我們可以把數(shù)據(jù)存儲(chǔ)在this上面,而在Function中,則我們可以通過利用 useRef 這個(gè) Hooks 來實(shí)現(xiàn)同樣的效果。
export default function Father1 (){
let [name,setName] = React.useState('');
const countContainer = React.useRef(0);
const getData=(count)=>{
//依據(jù)異步獲取數(shù)據(jù)
setTimeout(()=>{
setName("異步獲取回來的數(shù)據(jù)"+count)
countContainer.current = count++;
},200)
}
return (
<div>
<button onClick={()=>getData(++countContainer.current)}>點(diǎn)擊獲取數(shù)據(jù)</button>
{name}
</div>
)
}場(chǎng)景三:通過存入useRef的數(shù)據(jù)中,避免父子組件的重復(fù)刷新
假設(shè)父組件中有需要用到子組件的數(shù)據(jù),子組件需要把數(shù)據(jù)回到返回給父組件,而如果父組件把這份數(shù)據(jù)存入到了 state 中,那么父組件刷新,子組件也會(huì)跟著刷新。 這種的情況我們就可以把數(shù)據(jù)存入到 useRef 中,以避免無意義的刷新出現(xiàn)?;蛘甙褦?shù)據(jù)存入到class的 this 下。
四:合并 state,減少重復(fù) setState 的操作
合并 state ,減少重復(fù) setState 的操作,實(shí)際上 React已經(jīng)幫我們做了,那就是批量更新,在React18 之前的版本中,批量更新只有在 React自己的生命周期或者點(diǎn)擊事件中有提供,而異步更新則沒有,例如setTimeout,setInternal等。
所以如果我們想在React18 之前的版本中也想在異步代碼添加對(duì)批量更新的支持,就可以使用React給我們提供的api。
import ReactDOM from 'react-dom';
const { unstable_batchedUpdates } = ReactDOM;使用方法如下:
componentDidMount() {
setTimeout(()=>{
unstable_batchedUpdates(()=>{
this.setState({ number:this.state.number + 1 })
console.log(this.state.number)
this.setState({ number:this.state.number + 1})
console.log(this.state.number)
this.setState({ number:this.state.number + 1 })
console.log(this.state.number)
})
})
}五:如何更快的完成diff的比較,加快進(jìn)程
diff算法就是為了幫助我們找到需要更新的異同點(diǎn),那么有什么辦法可以讓我們的diff算法更快呢?
那就是合理的使用key
diff的調(diào)用是在reconcileChildren中的reconcileChildFibers,當(dāng)沒有可以復(fù)用current fiber節(jié)點(diǎn)時(shí),就會(huì)走mountChildFibers,當(dāng)有的時(shí)候就走reconcileChildFibers。
而reconcilerChildFibers的函數(shù)中則會(huì)針render函數(shù)返回的新的jsx數(shù)據(jù)進(jìn)行判斷,它是否是對(duì)象,就會(huì)判斷它的newChild.$$typeof是否是REACT_ELEMENT_TYPE,如果是就按單節(jié)點(diǎn)處理。 如果不是繼續(xù)判斷是否是REACT_PORTAL_TYPE或者REACT_LAZY_TYPE。
繼續(xù)判斷它是否為數(shù)組,或者可迭代對(duì)象。
而在單節(jié)點(diǎn)處理函數(shù)reconcileSingleElement中,會(huì)執(zhí)行如下邏輯:
- 通過
key,判斷上次更新的時(shí)候的Fiber節(jié)點(diǎn)是否存在對(duì)應(yīng)的DOM節(jié)點(diǎn)。 如果沒有 則直接走創(chuàng)建流程,新生成一個(gè) Fiber 節(jié)點(diǎn),并返回 - 如果有,那么就會(huì)繼續(xù)判斷,
DOM節(jié)點(diǎn)是否可以復(fù)用?
- 如果有,就將上次更新的
Fiber節(jié)點(diǎn)的副本作為本次新生的Fiber節(jié)點(diǎn)并返回
- 如果沒有,那么就標(biāo)記
DOM需要被刪除,新生成一個(gè)Fiber節(jié)點(diǎn)并返回。
function reconcileSingleElement(
returnFiber: Fiber,
currentFirstChild: Fiber | null,
element: ReactElement
): Fiber {
const key = element.key; //jsx 虛擬 DOM 返回的數(shù)據(jù)
let child = currentFirstChild;//當(dāng)前的fiber
// 首先判斷是否存在對(duì)應(yīng)DOM節(jié)點(diǎn)
while (child !== null) {
// 上一次更新存在DOM節(jié)點(diǎn),接下來判斷是否可復(fù)用
// 首先比較key是否相同
if (child.key === key) {
// key相同,接下來比較type是否相同
switch (child.tag) {
// ...省略case
default: {
if (child.elementType === element.type) {
// type相同則表示可以復(fù)用
// 返回復(fù)用的fiber
return existing;
}
// type不同則跳出switch
break;
}
}
// 代碼執(zhí)行到這里代表:key相同但是type不同
// 將該fiber及其兄弟fiber標(biāo)記為刪除
deleteRemainingChildren(returnFiber, child);
break;
} else {
// key不同,將該fiber標(biāo)記為刪除
deleteChild(returnFiber, child);
}
child = child.sibling;
}
// 創(chuàng)建新Fiber,并返回 ...省略
}從上面的代碼就可以看出,React 是如何判斷一個(gè) Fiber 節(jié)點(diǎn)是否可以被復(fù)用的。
- 第一步:判斷
element的key和fiber的key是否相同
- 如果不相同,就會(huì)創(chuàng)建新的
Fiber,并返回
- 第二步:如果相同,就判斷
element.type和fiber的type是否相同,type就是他們的類型,比如p標(biāo)簽就是p,div標(biāo)簽就是div.如果type不相同,那么就會(huì)標(biāo)識(shí)刪除。
- 如果相同,那就可以可以判斷可以復(fù)用了,返回
existing。
而在多節(jié)點(diǎn)更新的時(shí)候,key的作用則更加重要,React 會(huì)通過遍歷新舊數(shù)據(jù),數(shù)組和鏈表來通過按個(gè)判斷它們的key和 type 來決定是否復(fù)用。
所以我們需要合理的使用key來加快diff算法的比對(duì)和fiber的復(fù)用。
那么如何合理使用key呢。
其實(shí)很簡(jiǎn)單,只需要每一次設(shè)置的值和我們的數(shù)據(jù)一直就可以了。不要使用數(shù)組的下標(biāo),這種key和數(shù)據(jù)沒有關(guān)聯(lián),我們的數(shù)據(jù)發(fā)生了更新,結(jié)果 React 還指望著復(fù)用。
還有哪些工具可以提升性能呢?
實(shí)際的開發(fā)中還有其他的很多場(chǎng)景需要進(jìn)行優(yōu)化:
- 頻繁輸入或者滑動(dòng)滾動(dòng)的防抖節(jié)流
- 針對(duì)大數(shù)據(jù)展示的虛擬列表,虛擬表格
- 針對(duì)大數(shù)據(jù)展示的時(shí)間分片 等等等等 后面再補(bǔ)充吧!
到此這篇關(guān)于React 性能優(yōu)化方法總結(jié)的文章就介紹到這了,更多相關(guān)React 性能優(yōu)化內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
React項(xiàng)目中使用zustand狀態(tài)管理的實(shí)現(xiàn)
zustand是一個(gè)用于狀態(tài)管理的小巧而強(qiáng)大的庫,本文主要介紹了React項(xiàng)目中使用zustand狀態(tài)管理的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下2023-10-10
ReactJS應(yīng)用程序中設(shè)置Axios攔截器方法demo
這篇文章主要為大家介紹了ReactJS應(yīng)用程序中設(shè)置Axios攔截器方法demo,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12
react中form.setFieldvalue數(shù)據(jù)回填時(shí) value和text不對(duì)應(yīng)的問題及解決方法
這篇文章主要介紹了react中form.setFieldvalue數(shù)據(jù)回填時(shí) value和text不對(duì)應(yīng)的問題及解決方法,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-07-07
React-View-UI組件庫封裝Loading加載中源碼
這篇文章主要介紹了React-View-UI組件庫封裝Loading加載樣式,主要包括組件介紹,組件源碼及組件測(cè)試源碼,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-06-06
可定制react18 input otp 一次性密碼輸入組件
這篇文章主要為大家介紹了可定制react18 input otp 一次性密碼輸入組件,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10
React應(yīng)用中避免白屏現(xiàn)象的方法小結(jié)
在開發(fā)React應(yīng)用程序時(shí),我們都曾遇到過這樣的場(chǎng)景:一個(gè)未被捕獲的異常突然中斷了組件的渲染流程,導(dǎo)致用戶界面呈現(xiàn)出一片空白,也就是俗稱的“白屏”現(xiàn)象,本文將探討如何在React應(yīng)用中有效捕獲并處理這些錯(cuò)誤,避免白屏現(xiàn)象的發(fā)生,需要的朋友可以參考下2024-06-06
在React頁面重新加載時(shí)保留數(shù)據(jù)的實(shí)現(xiàn)方法總結(jié)
在React頁面重新加載時(shí)保留數(shù)據(jù),可以通過多種方法來實(shí)現(xiàn),常見的方法包括使用瀏覽器的本地存儲(chǔ)(Local Storage 或 Session Storage)、URL參數(shù)、以及服務(wù)器端存儲(chǔ)等,本文給大家總結(jié)了一些具體實(shí)現(xiàn)方法,需要的朋友可以參考下2024-06-06

