最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

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

說(shuō)明

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

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

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

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

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

項(xiàng)目中常見會(huì)導(dǎo)致重復(fù)渲染的寫法以及改進(jìn)方法

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

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

這樣的寫法每次父組件 render 都會(huì)新聲明一個(gè) function 傳遞給子組件,會(huì)導(dǎo)致 observer 失去比對(duì)作用,父組件每次 render 都會(huì)使這個(gè)組件 render,嚴(yán)重影響性能!

import React from 'react';
import { observer } from 'mobx-react';
// 我們開發(fā)中常見的一個(gè)被觀測(cè)組件,例如 ObserverComponent
@observer
class ObserverComponent extends React.Component {
    render() {
        return (<div>ObserverComponent</div>)
    }
}
// 例如在父組件 Parent 使用被觀測(cè)的子組件 ObserverComponent
// 請(qǐng)不要給子組件 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={() => {}}                      // 【錯(cuò)誤】
                onChange={this.handleChange.bind(this)}  // 【錯(cuò)誤】
                onChange={this.handleChange}             // 【正確】
                todo={this.doSomething}                  // 【正確】
            />
        )
    }
}

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

由于字面量的寫法{} 和 { pageSizeOptions: ['10'] },每次都會(huì)字面量聲明一個(gè)新的對(duì)象傳遞給列表組件,導(dǎo)致頁(yè)面重新 render。

toJS() 方法每次也會(huì)返回新對(duì)象,會(huì)導(dǎo)致頁(yè)面重新渲染

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

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

render執(zhí)行會(huì)帶來(lái)兩個(gè)方面的影響

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

針對(duì)上述問題, react給出來(lái)解決方案:

  • pureComponent
  • React.memo
  • useMemo
  • useCallback

下面將具體說(shuō)明這幾個(gè)都使用場(chǎng)景和解決的問題

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

具體是將當(dāng)前組件中一個(gè)經(jīng)過(guò)很復(fù)雜的計(jì)算得到的值緩存起來(lái), 當(dāng)其依賴項(xiàng)不變的時(shí)候, 即使組件重新渲染, 也不會(huì)重新計(jì)算。

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

/*
緩存了一個(gè)對(duì)象, 只有當(dāng)count變化時(shí)才會(huì)重新返回該對(duì)象
*/
const useInfo = useMemo(
    () => ({
        count: count,
        name: "name"
    }),
    [count]
)
  • 針對(duì)第二點(diǎn), 分別有三個(gè)解決方案

首先是useCallback, 其語(yǔ)法和useMemo基本一致, 但是其使用場(chǎng)景是父組件定義了一個(gè)函數(shù)并且將這個(gè)函數(shù)傳遞給了子組件, 那么當(dāng)父組件重新渲染時(shí),生成的會(huì)是一個(gè)新的函數(shù), 這個(gè)時(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ù),只初始化一次這個(gè)函數(shù),下次不產(chǎn)生新的函數(shù)
        </>
    )
}

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

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

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

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

  • 接著是pureComponent

它是一個(gè)類, 組件繼承自它后, 其作為子組件時(shí), 每次父組件更新后, 會(huì)淺對(duì)比傳來(lái)的props是否變化, 若沒變化, 則子組件不更新。

  • React.memo

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

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

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

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

相關(guān)文章

  • React大文件分片上傳原理及方案

    React大文件分片上傳原理及方案

    前端進(jìn)行大文件分片上傳的方案幾乎都是利用Blob.prototype.slice方法對(duì)文件進(jìn)行分片,用數(shù)組將每一個(gè)分片存起來(lái),最后將分片發(fā)給后端,本文給大家介紹React大文件分片上傳方案,感興趣的朋友跟隨小編一起看看吧
    2023-08-08
  • React Native 圖片查看組件的方法

    React Native 圖片查看組件的方法

    這篇文章主要介紹了React Native 圖片查看組件的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-03-03
  • React 中的 useContext使用方法

    React 中的 useContext使用方法

    這篇文章主要介紹了React中的useContext使用,使用useContext在改變一個(gè)數(shù)據(jù)時(shí),是通過(guò)自己逐級(jí)查找對(duì)比改變的數(shù)據(jù)然后渲染,本文通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-08-08
  • React?中的?setState?是同步還是異步

    React?中的?setState?是同步還是異步

    這篇文章主要介紹了React?中的?setState?是同步還是異步,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-06-06
  • React項(xiàng)目中className運(yùn)用及問題解決

    React項(xiàng)目中className運(yùn)用及問題解決

    這篇文章主要為大家介紹了React項(xiàng)目中className運(yùn)用及問題解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • 基于React實(shí)現(xiàn)調(diào)用式Modal組件的全流程

    基于React實(shí)現(xiàn)調(diào)用式Modal組件的全流程

    本文基于 nextUI 和 tailwindCSS 實(shí)現(xiàn)調(diào)用式 Modal 組件的封裝,文中通過(guò)圖文結(jié)合的方式和代碼示例介紹的非常詳細(xì),具有一定的參考價(jià)值,需要的朋友可以參考下
    2024-12-12
  • Native?Memory?Tracking追蹤區(qū)域示例分析

    Native?Memory?Tracking追蹤區(qū)域示例分析

    這篇文章主要為大家介紹了Native?Memory?Tracking追蹤區(qū)域示例分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-11-11
  • 一個(gè)基于react的圖片裁剪組件示例

    一個(gè)基于react的圖片裁剪組件示例

    本篇文章主要介紹了一個(gè)基于react的圖片裁剪組件示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-04-04
  • 詳解如何使用React和MUI創(chuàng)建多選Checkbox樹組件

    詳解如何使用React和MUI創(chuàng)建多選Checkbox樹組件

    這篇文章主要為大家詳細(xì)介紹了如何使用 React 和 MUI(Material-UI)庫(kù)來(lái)創(chuàng)建一個(gè)多選 Checkbox 樹組件,該組件可以用于展示樹形結(jié)構(gòu)的數(shù)據(jù),并允許用戶選擇多個(gè)節(jié)點(diǎn),感興趣的可以了解下
    2024-01-01
  • React 并發(fā)功能體驗(yàn)(前端的并發(fā)模式)

    React 并發(fā)功能體驗(yàn)(前端的并發(fā)模式)

    React 是由 Facebook 軟件工程師 Jordan Walke 創(chuàng)建,React 的第一個(gè)版本在七年前問世,現(xiàn)在,F(xiàn)acebook 負(fù)責(zé)維護(hù),本文給大家介紹React 并發(fā)功能體驗(yàn)前端并發(fā)模式的問題,感興趣的朋友跟隨小編一起看看吧
    2021-07-07

最新評(píng)論

临西县| 宜兴市| 鄂托克旗| 封开县| 马公市| 凤冈县| 巴中市| 陇西县| 永顺县| 元氏县| 金华市| 新密市| 广元市| 金门县| 拉孜县| 麻阳| 温宿县| 常山县| 铁力市| 科尔| 西安市| 伊通| 闵行区| 德保县| 双牌县| 龙川县| 株洲县| 叙永县| 东乡| 长顺县| 阳曲县| 旺苍县| 伊春市| 阳高县| 浦县| 龙江县| 靖安县| 河津市| 合肥市| 乌拉特前旗| 巴塘县|