亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

React前端渲染優(yōu)化--父組件導致子組件重復(fù)渲染的問題

 更新時間:2022年08月04日 15:22:08   作者:DominicElvira  
本篇文章是針對父組件導致子組件重復(fù)渲染的優(yōu)化方法,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

React前端渲染優(yōu)化--父組件導致子組件重復(fù)渲染

說明

目前我們所使用 react 版本一般會有以下四種方式觸發(fā)渲染 render,而其中通過父組件 render 會直接通知子組件也進行 render。

一般的優(yōu)化方式

鑒于此種情況,如果完全不做控制下,父組件 render, 那么子組件一定會 render。真實 dom 的渲染 react 會在 diff 算法之后合計出最小改動,進行操作。但對于結(jié)構(gòu)復(fù)雜頁面,自頂向下,只是單純 diff 也要花費很長的時間來處理 js 任務(wù)。再加上我們每個組件的 render 中也會寫很多業(yè)務(wù)、數(shù)據(jù)處理。

js 為單線程執(zhí)行,顯然,不必要的子組件的 render 會浪費 js 線程資源,復(fù)雜任務(wù)還會長時間占用線程導致假死狀態(tài),也就是頁面卡頓,react 底層有 Fiber 來優(yōu)化任務(wù)隊列,但無法優(yōu)化業(yè)務(wù)代碼上的問題。

一般子組件可以通過確認 props 是否發(fā)生變化來控制自身是否進行 render,比如 react-mobx 中的 observer 高階方法或者 React.PureComponet 就是用來做淺層比較進行控制處理。

項目中常見會導致重復(fù)渲染的寫法以及改進方法

函數(shù)導致的渲染重復(fù)

箭頭函數(shù) props.fn = () => {} 或者 綁定方法 props.fn = this.xxx.bind(this)

這樣的寫法每次父組件 render 都會新聲明一個 function 傳遞給子組件,會導致 observer 失去比對作用,父組件每次 render 都會使這個組件 render,嚴重影響性能!

import React from 'react';
import { observer } from 'mobx-react';
// 我們開發(fā)中常見的一個被觀測組件,例如 ObserverComponent
@observer
class ObserverComponent extends React.Component {
    render() {
        return (<div>ObserverComponent</div>)
    }
}
// 例如在父組件 Parent 使用被觀測的子組件 ObserverComponent
// 請不要給子組件 ObserverComponent 的 props 設(shè)置 箭頭函數(shù) () => {} 或者 fn.bind(this) 方法
@observer
class Parent extends React.Component {
    constructor(props) {
        super(props);
        this.handleChange = this.handleChange.bind(this); // 【正確】
    }
    handleChange() {}
    doSomething = () => {}
    render() {
        return (
            <ObserverComponent
                onChange={() => {}}                      // 【錯誤】
                onChange={this.handleChange.bind(this)}  // 【錯誤】
                onChange={this.handleChange}             // 【正確】
                todo={this.doSomething}                  // 【正確】
            />
        )
    }
}

字面量寫法導致的渲染重復(fù)

由于字面量的寫法{} 和 { pageSizeOptions: ['10'] },每次都會字面量聲明一個新的對象傳遞給列表組件,導致頁面重新 render。

toJS() 方法每次也會返回新對象,會導致頁面重新渲染

組件重復(fù)渲染問題(pureComponent, React.memo, useMemo, useCallback)

在一個組件中, 其state變化會引起render的重新執(zhí)行, 函數(shù)式組件中, 使用setHook更新state也會引起render的重新執(zhí)行

render執(zhí)行會帶來兩個方面的影響

  • 1.當前組件需要重新渲染, 除了那些狀態(tài)和生命周期初始化被保留的,其余正常的都會重新執(zhí)行。
  • 2.子組件會重新渲染, 即使其是一個無狀態(tài)組件

針對上述問題, react給出來解決方案:

  • pureComponent
  • React.memo
  • useMemo
  • useCallback

下面將具體說明這幾個都使用場景和解決的問題

  • useMemo設(shè)計的初衷就是避免重復(fù)進行大規(guī)模的計算, 它的理想作用對象是當前組件

具體是將當前組件中一個經(jīng)過很復(fù)雜的計算得到的值緩存起來, 當其依賴項不變的時候, 即使組件重新渲染, 也不會重新計算。

通過上述描述也能理解出其緩存的是一個具體的數(shù)據(jù)(可以和接下來的useCallback區(qū)分開)

/*
緩存了一個對象, 只有當count變化時才會重新返回該對象
*/
const useInfo = useMemo(
    () => ({
        count: count,
        name: "name"
    }),
    [count]
)
  • 針對第二點, 分別有三個解決方案

首先是useCallback, 其語法和useMemo基本一致, 但是其使用場景是父組件定義了一個函數(shù)并且將這個函數(shù)傳遞給了子組件, 那么當父組件重新渲染時,生成的會是一個新的函數(shù), 這個時候就可以使用useCallback了,如下:

const Page = (props) => {
    const [count, setCount] = useState(0);
    const [name, setName] = useState('Child組件');
    return (
        <>
            <ChildMemo name={name} onClick={ useCallback((newName: string) => setName(newName), []) }/>
            {/* useCallback((newName: string) => setName(newName),[]) */}
            {/* 這里使用了useCallback優(yōu)化了傳遞給子組件的函數(shù),只初始化一次這個函數(shù),下次不產(chǎn)生新的函數(shù)
        </>
    )
}

上述是一個簡寫的形式,意思就是將傳遞給子組件的這個函數(shù)緩存了,其第二個參數(shù)就是依賴,當該依賴變化時,將會重新緩存該函數(shù)

其余useMemo的區(qū)別就在于,其緩存的是函數(shù)本身,而useMemo緩存的是函數(shù)計算后的值,都會在依賴項變化時重新緩存。

注:雖然其可能對于父組件傳遞給子組件函數(shù)時可能很理想,但實際上其帶來的性能損耗也是顯而易見的,其使用場景不應(yīng)該是擔心本組件的函數(shù)因為本組件重新渲染而重新生成,這樣反而起到了反效果,當前組件更新,其重新渲染,內(nèi)部的函數(shù)也重新生成,其性能損耗可以忽略不計,如下圖。

使用場景應(yīng)該是父組件更新導致重新生成的函數(shù)又傳遞給了子組件,導致子組件重新渲染。

  • 接著是pureComponent

它是一個類, 組件繼承自它后, 其作為子組件時, 每次父組件更新后, 會淺對比傳來的props是否變化, 若沒變化, 則子組件不更新。

  • React.memo

同上條功能類似, 當其作用于函數(shù)式組件并且作為子組件時, 每次父組件更新后, 會淺對比傳來的props是否變化, 若沒變化, 則子組件不更新。

// 子組件暴露時暴露為處理后的組件
import {memo} from 'react'
const TeacherModal = (props: any) => {
  return <div></div>
}
export default memo(TeacherModal)

上面兩個都區(qū)別在于, 一個是類, 一個是高階組件, 前者作用于類后者作用于函數(shù)

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 利用CDN加速react webpack打包后的文件詳解

    利用CDN加速react webpack打包后的文件詳解

    下面小編就為大家分享一篇利用CDN加速react webpack打包后的文件詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-02-02
  • react native 原生模塊橋接的簡單說明小結(jié)

    react native 原生模塊橋接的簡單說明小結(jié)

    這篇文章主要介紹了react native 原生模塊橋接的簡單說明小結(jié),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-02-02
  • antd-react使用Select組件defaultValue踩的坑及解決

    antd-react使用Select組件defaultValue踩的坑及解決

    這篇文章主要介紹了antd-react使用Select組件defaultValue踩的坑及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-05-05
  • 詳解React 服務(wù)端渲染方案完美的解決方案

    詳解React 服務(wù)端渲染方案完美的解決方案

    這篇文章主要介紹了詳解React 服務(wù)端渲染方案完美的解決方案,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-12-12
  • react結(jié)合bootstrap實現(xiàn)評論功能

    react結(jié)合bootstrap實現(xiàn)評論功能

    這篇文章主要為大家詳細介紹了react結(jié)合bootstrap實現(xiàn)評論功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-05-05
  • react中的虛擬dom和diff算法詳解

    react中的虛擬dom和diff算法詳解

    這篇文章主要介紹了react中的虛擬dom和diff算法,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-04-04
  • React實現(xiàn)點擊刪除列表中對應(yīng)項

    React實現(xiàn)點擊刪除列表中對應(yīng)項

    本文主要介紹了React 點擊刪除列表中對應(yīng)項的方法。具有一定的參考價值,下面跟著小編一起來看下吧
    2017-01-01
  • React可定制黑暗模式切換開關(guān)組件

    React可定制黑暗模式切換開關(guān)組件

    這篇文章主要為大家介紹了React可定制黑暗模式切換開關(guān)組件示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-10-10
  • React-View-UI組件庫封裝Loading加載中源碼

    React-View-UI組件庫封裝Loading加載中源碼

    這篇文章主要介紹了React-View-UI組件庫封裝Loading加載樣式,主要包括組件介紹,組件源碼及組件測試源碼,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-06-06
  • React-Route6實現(xiàn)keep-alive效果

    React-Route6實現(xiàn)keep-alive效果

    本文主要介紹了React-Route6實現(xiàn)keep-alive效果,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧<BR>
    2022-06-06

最新評論