欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

React?組件性能最佳優(yōu)化實踐分享

 更新時間:2022年09月14日 09:06:29   作者:Tecode???????  
這篇文章主要介紹了React組件性能最佳優(yōu)化實踐分享,React組件性能優(yōu)化的核心是減少渲染真實DOM節(jié)點(diǎn)的頻率,減少Virtual?DOM比對的頻率,更多相關(guān)內(nèi)容需要的朋友可以參考一下

React 組件性能優(yōu)化最佳實踐

React 組件性能優(yōu)化的核心是減少渲染真實 DOM 節(jié)點(diǎn)的頻率,減少 Virtual DOM 比對的頻率。如果子組件未發(fā)生數(shù)據(jù)改變不渲染子組件。

組件卸載前進(jìn)行清理操作

以下代碼在組件掛載時會創(chuàng)建一個interval組件銷毀后清除定時器,間隔1秒會觸發(fā)渲染count+1,組件銷毀后如果不清除定時器它會一直消耗資源

import React, { useState, useEffect } from "react"
import ReactDOM from "react-dom"

const App = () => {
  let [index, setIndex] = useState(0)
  useEffect(() => {
    let timer = setInterval(() => {
      setIndex(prev => prev + 1)
      console.log('timer is running...')
    }, 1000)
    return () => clearInterval(timer)
  }, [])
  return (
    <button onClick={() => ReactDOM.unmountComponentAtNode(document.getElementById("root"))}>
      {index}
    </button>
  )
}

export default App

每次數(shù)據(jù)更新都會觸發(fā)組件重新渲染,這里的優(yōu)化為:組件銷毀清理定時器

類組件使用純組件PureComponent

什么是純組件

純組件會對組件輸入數(shù)據(jù)進(jìn)行淺層比較,如果當(dāng)前輸入數(shù)據(jù)和上次輸入數(shù)據(jù)相同,組件不會重新渲染

什么是淺層比較

比較引用數(shù)據(jù)類型在內(nèi)存中的引用地址是否相同,比較基本數(shù)據(jù)類型的值是否相同。

為什么不直接進(jìn)行 diff 操作, 而是要先進(jìn)行淺層比較,淺層比較難道沒有性能消耗嗎

和進(jìn)行 diff 比較操作相比,淺層比較將消耗更少的性能。diff 操作會重新遍歷整顆 virtualDOM 樹, 而淺層比較只操作當(dāng)前組件的 state 和 props。

import React from "react"
export default class App extends React.Component {
  constructor() {
    super()
    this.state = {name: "張三"}
  }
  updateName() {
    setInterval(() => this.setState({name: "張三"}), 1000)
  }
  componentDidMount() {
    this.updateName()
  }
  render() {
    return (
      <div>
        <RegularComponent name={this.state.name} />
        <PureChildComponent name={this.state.name} />
      </div>
    )
  }
}
class RegularComponent extends React.Component {
  render() {
    console.log("RegularComponent")
    return <div>{this.props.name}</div>
  }
}

class PureChildComponent extends React.PureComponent {
  render() {
    console.log("PureChildComponent")
    return <div>{this.props.name}</div>
  }
}

組件掛載以后會有一個定時器間隔1秒設(shè)置一次name,我們可以看到RegularComponent一直在渲染,即使數(shù)據(jù)沒有發(fā)生變化也會渲染。PureChildComponent只有一次渲染,因此使用純組件會對props state進(jìn)行進(jìn)行比較,數(shù)據(jù)相同不會重新渲染。

shouldComponentUpdate

純組件只能進(jìn)行淺層比較,要進(jìn)行深層比較,使用 shouldComponentUpdate,它用于編寫自定義比較邏輯。

返回 true 重新渲染組件,返回 false 阻止重新渲染。

函數(shù)的第一個參數(shù)為 nextProps, 第二個參數(shù)為 nextState。

import React from "react"

export default class App extends React.Component {
  constructor() {
    super()
    this.state = {name: "張三", age: 20, job: "waiter"}
  }
  componentDidMount() {
    setTimeout(() => this.setState({ job: "chef" }), 1000)
  }
  shouldComponentUpdate(nextProps, nextState) {
    if (this.state.name !== nextState.name || this.state.age !== nextState.age) {
      return true
    }
    return false
  }
  render() {
    console.log("rendering")
    let { name, age } = this.state
    return <div>{name} {age}</div>
  }
}

即使繼承了Component的組件定時器一直修改數(shù)據(jù)也不會觸發(fā)重新渲染

純函數(shù)組件使用React.memo優(yōu)化性能

memo 基本使用

將函數(shù)組件變?yōu)榧兘M件,將當(dāng)前 props 和上一次的 props 進(jìn)行淺層比較,如果相同就阻止組件重新渲染。

import React, { memo, useEffect, useState } from "react"
function ShowName({ name }) {
  console.log("showName render...")
  return <div>{name}</div>
}

const ShowNameMemo = memo(ShowName)
function App() {
  const [index, setIndex] = useState(0)
  const [name] = useState("張三")
  useEffect(() => {
    setInterval(() => {
      setIndex(prev => prev + 1)
    }, 1000)
  }, [])
  return (
    <div>
      {index}
      <ShowNameMemo name={name} />
    </div>
  )
}
export default App

memo 傳遞比較邏輯

(使用 memo方法自定義比較邏輯,用于執(zhí)行深層比較。)

import React, { memo, useEffect, useState } from "react";

function ShowName({ person }) {
  console.log("showName render...");
  return (
    <div>
      {person.name}
      丨
      {person.job}
    </div>
  );
}

function comparePerson(prevProps, nextProps) {
  if (
    prevProps.person.name !== nextProps.person.name ||
    prevProps.person.age !== nextProps.person.age
  ) {
    return false
  }
  return true
}
const ShowNameMemo = memo(ShowName, comparePerson);
function App() {
  const [person, setPerson] = useState({ name: "張三", job: "developer" });
  useEffect(() => {
    setInterval(() => {
      setPerson((data) => ({ ...data, name: "haoxuan" }));
    }, 1000);
  }, []);
  return (
    <div>
      <ShowNameMemo person={person} />
    </div>
  );
}
export default App;

使用組件懶加載

使用組件懶加載可以減少 bundle 文件大小, 加快組件呈遞速度。

路由組件懶加載

import React, { lazy, Suspense } from "react"
import { BrowserRouter, Link, Route, Switch } from "react-router-dom"

const Home = lazy(() => import(/* webpackChunkName: "Home" */ "./Home"))
const List = lazy(() => import(/* webpackChunkName: "List" */ "./List"))

function App() {
  return (
    <BrowserRouter>
      <Link to="/">Home</Link>
      <Link to="/list">List</Link>
      <Switch>
        <Suspense fallback={<div>Loading</div>}>
          <Route path="/" component={Home} exact />
          <Route path="/list" component={List} />
        </Suspense>
      </Switch>
    </BrowserRouter>
  )
}
export default App

根據(jù)條件進(jìn)行組件懶加載(適用于組件不會隨條件頻繁切換)

import React, { lazy, Suspense } from "react"

function App() {
  let LazyComponent = null
  if (true) {
    LazyComponent = lazy(() => import(/* webpackChunkName: "Home" */ "./Home"))
  } else {
    LazyComponent = lazy(() => import(/* webpackChunkName: "List" */ "./List"))
  }
  return (
    <Suspense fallback={<div>Loading</div>}>
      <LazyComponent />
    </Suspense>
  )
}
export default App

使用Fragment 避免額外標(biāo)記

為了滿足這個條件我們通常都會在最外層添加一個div, 但是這樣的話就會多出一個無意義的標(biāo)記, 如果每個組件都多出這樣的一個無意義標(biāo)記的話, 瀏覽器渲染引擎的負(fù)擔(dān)就會加劇。

import { Fragment } from "react"

function App() {
  return (
    <Fragment>
      <div>message a</div>
      <div>message b</div>
    </Fragment>
  )
}
function App() {
  return (
    <>
      <div>message a</div>
      <div>message b</div>
    </>
  )
}

不要使用內(nèi)聯(lián)函數(shù)定義

在使用內(nèi)聯(lián)函數(shù)后, render 方法每次運(yùn)行時都會創(chuàng)建該函數(shù)的新實例, 導(dǎo)致 React 在進(jìn)行 Virtual DOM 比對時, 新舊函數(shù)比對不相等,導(dǎo)致 React 總是為元素綁定新的函數(shù)實例, 而舊的函數(shù)實例又要交給垃圾回收器處理。

錯誤示范:

import React from "react"

export default class App extends React.Component {
  constructor() {
    super()
    this.state = {
      inputValue: ""
    }
  }
  render() {
    return (
      <input
        value={this.state.inputValue}
        onChange={e => this.setState({ inputValue: e.target.value })}
        />
    )
  }
}

正確的做法是在組件中單獨(dú)定義函數(shù), 將函數(shù)綁定給事件:

import React from "react"

export default class App extends React.Component {
  constructor() {
    super()
    this.state = {
      inputValue: ""
    }
  }
  setInputValue = e => {
    this.setState({ inputValue: e.target.value })
  }
  render() {
    return (
      <input value={this.state.inputValue} onChange={this.setInputValue} />
    )
  }
}

在構(gòu)造函數(shù)中進(jìn)行函數(shù)this綁定

在類組件中如果使用 fn() {} 這種方式定義函數(shù), 函數(shù) this 默認(rèn)指向 undefined. 也就是說函數(shù)內(nèi)部的 this 指向需要被更正.

可以在構(gòu)造函數(shù)中對函數(shù)的 this 進(jìn)行更正, 也可以在行內(nèi)進(jìn)行更正, 兩者看起來沒有太大區(qū)別, 但是對性能的影響是不同的

export default class App extends React.Component {
   constructor() {
    super()
     // 方式一
     // 構(gòu)造函數(shù)只執(zhí)行一次, 所以函數(shù) this 指向更正的代碼也只執(zhí)行一次.
    this.handleClick = this.handleClick.bind(this)
  }
  handleClick() {
    console.log(this)
  }
  render() {
    // 方式二 
    // 問題: render 方法每次執(zhí)行時都會調(diào)用 bind 方法生成新的函數(shù)實例.
    return <button onClick={this.handleClick.bind(this)}>按鈕</button>
  }
}

類組件中的箭頭函數(shù)

在類組件中使用箭頭函數(shù)不會存在 this 指向問題, 因為箭頭函數(shù)本身并不綁定 this。

export default class App extends React.Component {
  handleClick = () => console.log(this)
  render() {
    return <button onClick={this.handleClick}>按鈕</button>
  }
}

箭頭函數(shù)在 this 指向問題上占據(jù)優(yōu)勢, 但是同時也有不利的一面.

當(dāng)使用箭頭函數(shù)時, 該函數(shù)被添加為類的實例對象屬性, 而不是原型對象屬性. 如果組件被多次重用, 每個組件實例對象中都將會有一個相同的函數(shù)實例, 降低了函數(shù)實例的可重用性造成了資源浪費(fèi).

綜上所述, 更正函數(shù)內(nèi)部 this 指向的最佳做法仍是在構(gòu)造函數(shù)中使用 bind 方法進(jìn)行綁定

優(yōu)化條件渲染

頻繁的掛載和卸載組件是一項耗性能的操作, 為了確保應(yīng)用程序的性能, 應(yīng)該減少組件掛載和卸載的次數(shù).

在 React 中我們經(jīng)常會根據(jù)條件渲染不同的組件. 條件渲染是一項必做的優(yōu)化操作。

function App() {
  if (true) {
    return (
      <>
        <AdminHeader />
        <Header />
        <Content />
      </>
    )
  } else {
    return (
      <>
        <Header />
        <Content />
      </>
    )
  }
}

在上面的代碼中, 當(dāng)渲染條件發(fā)生變化時, React 內(nèi)部在做 Virtual DOM 比對時發(fā)現(xiàn), 剛剛第一個組件是 AdminHeader, 現(xiàn)在第一個組件是 Header, 剛剛第二個組件是 Header, 現(xiàn)在第二個組件是 Content, 組件發(fā)生了變化, React 就會卸載 AdminHeader、Header、Content, 重新掛載 Header 和 Content, 這種掛載和卸載就是沒有必要的。

function App() {
  return (
    <>
      {true && <AdminHeader />}
      <Header />
      <Content />
    </>
  )
}

避免使用內(nèi)聯(lián)樣式屬性

當(dāng)使用內(nèi)聯(lián) style 為元素添加樣式時, 內(nèi)聯(lián) style 會被編譯為 JavaScript 代碼, 通過 JavaScript 代碼將樣式規(guī)則映射到元素的身上, 瀏覽器就會花費(fèi)更多的時間執(zhí)行腳本和渲染 UI, 從而增加了組件的渲染時間。

function App() {
  return <div style={{ backgroundColor: "skyblue" }}>App works</div>
}

避免重復(fù)無限渲染

當(dāng)應(yīng)用程序狀態(tài)發(fā)生更改時, React 會調(diào)用 render 方法, 如果在 render 方法中繼續(xù)更改應(yīng)用程序狀態(tài), 就會發(fā)生 render 方法遞歸調(diào)用導(dǎo)致應(yīng)用報錯.

export default class App extends React.Component {
  constructor() {
    super()
    this.state = {name: "張三"}
  }
  render() {
    this.setState({name: "李四"})
    return <div>{this.state.name}</div>
  }
}

與其他生命周期函數(shù)不同, render 方法應(yīng)該被作為純函數(shù). 這意味著, 在 render 方法中不要做以下事情, 比如不要調(diào)用 setState 方法, 不要使用其他手段查詢更改原生 DOM 元素, 以及其他更改應(yīng)用程序的任何操作. render 方法的執(zhí)行要根據(jù)狀態(tài)的改變, 這樣可以保持組件的行為和渲染方式一致.

避免數(shù)據(jù)結(jié)構(gòu)突變

組件中 props 和 state 的數(shù)據(jù)結(jié)構(gòu)應(yīng)該保持一致, 數(shù)據(jù)結(jié)構(gòu)突變會導(dǎo)致輸出不一致.

import React, { Component } from "react"

export default class App extends Component {
  constructor() {
    super()
    this.state = {
      employee: {
        name: "張三",
        age: 20
      }
    }
  }
  render() {
    const { name, age } = this.state.employee
    return (
      <div>
        {name}
        {age}
        <button
          onClick={() =>
            this.setState({
              ...this.state,
              employee: {
                ...this.state.employee,
                age: 30
              }
            })
          }
        >
          change age
        </button>
      </div>
    )
  }
}

到此這篇關(guān)于React 組件性能最佳優(yōu)化實踐分享的文章就介紹到這了,更多相關(guān)React 組件性能優(yōu)化內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • React中組件通信的幾種主要方式

    React中組件通信的幾種主要方式

    React知識中一個主要內(nèi)容便是組件之間的通信,以下列舉幾種常用的組件通信方式,通過代碼示例介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2024-10-10
  • React父子組件傳值(組件通信)的實現(xiàn)方法

    React父子組件傳值(組件通信)的實現(xiàn)方法

    本文主要介紹了React父子組件傳值(組件通信)的實現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-05-05
  • 使用hooks寫React組件需要注意的5個地方

    使用hooks寫React組件需要注意的5個地方

    這篇文章主要介紹了使用hooks寫React組件需要注意的5個地方,幫助大家更好的理解和學(xué)習(xí)使用React組件,感興趣的朋友可以了解下
    2021-04-04
  • React如何使用refresh_token實現(xiàn)無感刷新頁面

    React如何使用refresh_token實現(xiàn)無感刷新頁面

    本文主要介紹了React如何使用refresh_token實現(xiàn)無感刷新頁面,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-04-04
  • 探究react-native 源碼的圖片緩存問題

    探究react-native 源碼的圖片緩存問題

    本篇文章主要介紹了探究react-native 源碼的圖片緩存問題,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-08-08
  • react-router-dom入門使用教程(路由的模糊匹配與嚴(yán)格匹配)

    react-router-dom入門使用教程(路由的模糊匹配與嚴(yán)格匹配)

    這篇文章主要介紹了react-router-dom入門使用教程,主要介紹路由的模糊匹配與嚴(yán)格匹配,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-08-08
  • react中hooks使用useState的更新不觸發(fā)dom更新問題及解決

    react中hooks使用useState的更新不觸發(fā)dom更新問題及解決

    這篇文章主要介紹了react中hooks使用useState的更新不觸發(fā)dom更新問題及解決,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • react?echarts?tree樹圖搜索展開功能示例詳解

    react?echarts?tree樹圖搜索展開功能示例詳解

    這篇文章主要為大家介紹了react?echarts?tree樹圖搜索展開功能示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-01-01
  • React組件設(shè)計過程之仿抖音訂單組件

    React組件設(shè)計過程之仿抖音訂單組件

    這篇文章主要介紹了React組件設(shè)計過程之仿抖音訂單組件的實現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07
  • 作為老司機(jī)使用 React 總結(jié)的 11 個經(jīng)驗教訓(xùn)

    作為老司機(jī)使用 React 總結(jié)的 11 個經(jīng)驗教訓(xùn)

    這篇文章主要介紹了作為老司機(jī)使用 React 總結(jié)的 11 個經(jīng)驗教訓(xùn),需要的朋友可以參考下
    2017-04-04

最新評論