国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

客戶端性能優(yōu)化實踐

這篇具有很好參考價值的文章主要介紹了客戶端性能優(yōu)化實踐。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

背景

雙十一大促時,客戶客服那邊反饋商品信息加載卡頓,在不斷有訂單咨詢時,甚至出現(xiàn)了商品信息一直處于加載狀態(tài)的情況,顯然,在這種高峰期接待客戶時,是沒法進行正常的接待工作的。
起初,頁面一直處于加載狀態(tài),初步認為是后端接口返回太慢導致,后經(jīng)過后端日志排查,發(fā)現(xiàn)接口返回很快,根本不會造成頁面一直處于加載狀態(tài),甚至出現(xiàn)卡死的狀態(tài)。后經(jīng)過不斷排查,發(fā)現(xiàn)是客戶端性能問題導致。

優(yōu)化前

咨詢訂單時,只咨詢一條訂單,用時需要3秒左右,當連續(xù)咨詢5、6條訂單時,用時甚至達到了一分多鐘,僅僅5、6條訂單竟然用時這么久,那么在持續(xù)不斷有訂單咨詢時,頁面就會出現(xiàn)一直加載,甚至卡死的狀態(tài),明顯存在很大的性能問題。
客戶端性能優(yōu)化實踐,前端,react.js,性能優(yōu)化

客戶端性能優(yōu)化實踐,前端,react.js,性能優(yōu)化

利用performance工具可以分析主線程的Event Loop,圖中標出的Main就是主線程。
主線程是不斷執(zhí)行 Event Loop 的,可以看到有很多個 Task(宏任務(wù)),當主線程中的任務(wù)過多時,會導致主線程長時間被占用,無法及時響應(yīng)用戶的交互操作,從而影響用戶體驗。這種情況下,頁面可能會出現(xiàn)卡頓、延遲響應(yīng)等問題。

優(yōu)化后

當只咨詢一條訂單時,用時需要1秒時間,連續(xù)咨詢5、6條訂單,用時優(yōu)化到只需要3秒時間,并且頁面流暢,對于用戶體驗上得到了明顯的提升。
客戶端性能優(yōu)化實踐,前端,react.js,性能優(yōu)化
客戶端性能優(yōu)化實踐,前端,react.js,性能優(yōu)化

可以看出long task 減少了很多。
那么,如何來優(yōu)化呢?請看下面的內(nèi)容。

優(yōu)化點

在合適的時機進行組件渲染

在排查代碼的過程中發(fā)現(xiàn),很多本不該當前狀態(tài)渲染的組件,都渲染出來了,顯然這是不合理的。過多的組件渲染會占用大量的內(nèi)存,并且也會增加頁面的渲染時間,自然,響應(yīng)性能就會變得很差,用戶與頁面的交互就會變得遲緩。
而商品信息加載部分最常見的不必要的組件渲染表現(xiàn)在使用Modal彈窗時,我們都知道當visible為true時,會彈出彈窗相應(yīng)的頁面內(nèi)容,但是當visible為false時,其實是不希望渲染Modal彈窗中的內(nèi)容的,這會帶來額外的性能開銷。

下面是一些示例:

-  ...
-  <Modal
-   ...
-   visible={editVisible}
-   ...
   >
-  ...
-  </Modal>
-  ...
+  {editVisible && (
+     <GoodsAttributeModal
+      editVisible
+      ...
+     />
+  )}
// 把Modal彈窗作為一個單獨組件提取出去,并且只有當editVisible為true時才渲染組件

第一段代碼中,使用了visible={editVisible}來控制Modal組件的顯示與隱藏。當editVisible為true時,Modal組件會被渲染出來,否則不會被渲染。

第二段代碼中,使用了條件渲染的方式,即通過{editVisible && …}來判斷是否渲染Modal組件。當editVisible為true時,Modal組件會被渲染出來,否則不會被渲染。

這兩種方式的主要區(qū)別在于組件的渲染時機。在第一種方式中,Modal組件在每次渲染時都會被創(chuàng)建和銷毀,而在第二種方式中,只有在editVisible為true時才會創(chuàng)建和渲染Modal組件。

使用條件渲染的方式可以提高性能,特別是在組件層級較深或渲染頻繁的情況下。因為只有在需要顯示Modal組件時才會進行渲染,避免了不必要的組件創(chuàng)建和銷毀,減少了內(nèi)存消耗和渲染時間。

總結(jié)起來,使用條件渲染的方式可以根據(jù)需要動態(tài)地控制組件的顯示與隱藏,提高性能和用戶體驗。

使用useCallback、useMemo、React.memo提升性能

下面是一些示例:
useCallback

-  renderContent = (content, searchKey) => {
-   if(content) {
-     const contentWithBr = content.replace(/\?/g, '<br>').replace(/\n/g, '<br>')
-      const regex = new RegExp(`(${searchKey})`, 'gi'); // 創(chuàng)建正則表達式,忽略大小寫匹配
-      const matches = content.match(regex) || []; // 匹配結(jié)果數(shù)組
-      return (
-        <React.Fragment>
-          {contentWithBr.split('<br>').map((text, index) => (
-            <React.Fragment key={index}>
-              {index > 0 && <br />}
-              {text.split(regex).map((subText, subIndex) => {
-                // console.log('subText',subText,matches)
-                return (
-                  <React.Fragment key={subIndex}>
-                    {matches.includes(subText) ? (
-                      <span style={{ color: '#FF8800' }}>{subText}</span>
-                    ) : (
-                      subText
-                    )}
-                  </React.Fragment>
-                )
-              })}
-            </React.Fragment>
-          ))}
-        </React.Fragment>
-      )
-    } else {
-      return '-'
-    }
-  }

+  const renderContent = useCallback((content, searchKey) => {
+    if (content) {
+      const contentWithBr = content.replace(/\?/g, '<br>').replace(/\n/g, '<br>')
+      const regex = new RegExp(`(${searchKey})`, 'gi') // 創(chuàng)建正則表達式,忽略大小寫匹配
+      const matches = content.match(regex) || [] // 匹配結(jié)果數(shù)組
+      return (
+        <React.Fragment>
+          {contentWithBr.split('<br>').map((text, index) => (
+            <React.Fragment key={index}>
+              {index > 0 && <br />}
+              {text.split(regex).map((subText, subIndex) => {
+                //console.log('subText',subText,matches)
+                return (
+                  <React.Fragment key={subIndex}>
+                    {matches.includes(subText) ? (
+                      <span style={{ color: '#FF8800' }}>{subText}</span>
+                    ) : (
+                      subText
+                    )}
+                  </React.Fragment>
+                )
+              })}
+            </React.Fragment>
+          ))}
+        </React.Fragment>
+      )
+    } else {
+      return '-'
+    }
+  }, [])

上面的代碼使用了React的useCallback鉤子函數(shù)來定義了一個名為renderContent的函數(shù)。useCallback的作用是用來緩存函數(shù),以便在依賴項不變的情況下避免函數(shù)的重新創(chuàng)建。

使用useCallback的好處是可以優(yōu)化性能,特別是在父組件重新渲染時,避免不必要的函數(shù)重新創(chuàng)建。當依賴項數(shù)組為空時,useCallback會在組件的初始渲染時創(chuàng)建函數(shù),并在后續(xù)的渲染中重復使用同一個函數(shù)。

而沒有使用useCallback的情況下,每次組件重新渲染時都會創(chuàng)建一個新的renderContent函數(shù),即使函數(shù)的實現(xiàn)邏輯完全相同。這可能會導致性能問題,特別是在組件層級較深或渲染頻繁的情況下。

因此,使用useCallback可以提高組件的性能,避免不必要的函數(shù)創(chuàng)建和內(nèi)存消耗。但需要注意的是,只有在確實需要緩存函數(shù)并且依賴項不變的情況下才使用useCallback,否則可能會導致不必要的優(yōu)化和錯誤。

useMemo

-  const tooltip = (
-    <div>
-      <h2>
-        <span className={styles.title}>{title}</span>
-        {
-          !window.isVisibleGoods && (
-            <span>
-              {renderKnowledgeModal({
-                label: '編輯',
-                record: item,
-               platGoodsId: plat_goods_id,
-                classification_id: classificationId,
-              })}
-              <a
-                className={styles.delete}
-                onClick={() => handleDeleteKnowledage(item, classificationId)}
-              >
-                刪除
-              </a>
-            </span>
-          )
-        }        
-      </h2>
-      <div className={styles.img_block}>{images}</div>
-      <div
-        className={classnames(styles.context, styles.tooltipsContext)}
-        dangerouslySetInnerHTML={{ __html: ParseBrow.parse(context) }}
-      />
-    </div>
-  )
+ const tooltip = useMemo(
+    () => (
+      <div>
+        <h2>
+          <span className={styles.title}>{title}</span>
+          {!isVisibleGoods && (
+            <span>
+              {renderKnowledgeModal({
+                label: '編輯',
+                record: item,
+                platGoodsId: plat_goods_id,
+                classification_id: classificationId,
+              })}
+              <a
+                className={styles.delete}
+                onClick={() => handleDeleteKnowledage(item, classificationId)}
+              >
+                刪除
+             </a>
+            </span>
+          )}
+        </h2>
+        <div className={styles.img_block}>{images}</div>
+        <div
+          className={classnames(styles.context, styles.tooltipsContext)}
+          dangerouslySetInnerHTML={{ __html: ParseBrow.parse(context) }}
+        />
+      </div>
+    ),
+    [
+      title,
+      renderKnowledgeModal,
+      item,
+      plat_goods_id,
+      classificationId,
+      images,
+      context,
+      handleDeleteKnowledage,
+      isVisibleGoods,
+    ]
+  )

在上面的代碼中,使用了useMemo來緩存了一個變量tooltip的計算結(jié)果。這個計算結(jié)果是一個React元素,包含了一些子元素和事件處理函數(shù)等。通過將tooltip作為依賴數(shù)組的一部分,當依賴數(shù)組中的值發(fā)生變化時,useMemo會重新計算tooltip的值;如果依賴數(shù)組中的值沒有發(fā)生變化,則直接返回上一次緩存的tooltip的值。

這樣做的好處是,當依賴數(shù)組中的值沒有發(fā)生變化時,可以避免重復計算tooltip的值,提高組件的性能。而如果依賴數(shù)組中的值發(fā)生變化,useMemo會重新計算tooltip的值,確保tooltip的值是最新的。

相比之下,如果不使用useMemo,每次組件重新渲染時都會重新計算tooltip的值,即使依賴數(shù)組中的值沒有發(fā)生變化,這樣會造成不必要的性能損耗。

總結(jié)起來,使用useMemo可以優(yōu)化組件的性能,避免不必要的計算。但是需要注意的是,只有在計算的成本比較高時才需要使用useMemo,否則可能會帶來額外的開銷

React.memo

-  export default Item
+  import { isEqual } from 'lodash'
+  export default React.memo(Item, isEqual)

export default Item 直接導出組件,每次父組件重新渲染都會重新渲染 Item 組件;
而 export default React.memo(Item, isEqual) 使用 React.memo 進行包裹,并傳入自定義的比較函數(shù) isEqual,只有在 props 發(fā)生變化且通過 isEqual 函數(shù)比較不相等時才會重新渲染 Item 組件。
注意:自定義的比較函數(shù) isEqual 用于比較兩個 props 是否相等。如果不傳入比較函數(shù),則默認使用淺比較(即 Object.is)來比較 props。如果傳入了比較函數(shù),則會使用該函數(shù)來比較 props。

props解構(gòu)變量時的默認值

客戶端性能優(yōu)化實踐,前端,react.js,性能優(yōu)化

在這段代碼中,KnowledgeTab是一個使用了React.memo進行優(yōu)化的組件。React.memo是一個高階組件,用于對組件進行淺層比較,以確定是否需要重新渲染組件。當組件的props沒有發(fā)生變化時,React.memo會返回之前渲染的結(jié)果,從而避免不必要的重新渲染。

在KnowledgeTab組件中,knowledge_list是一個從props中解構(gòu)出來的屬性。而const knowledge_list_default = useMemo(() => [], [])是使用useMemo鉤子函數(shù)創(chuàng)建的一個空數(shù)組。這樣做的目的是為了在組件的初始渲染時,給knowledge_list一個默認值,以避免在解構(gòu)時出現(xiàn)undefined的情況。

如果直接使用knowledge_list=[]來給knowledge_list賦值,會破壞React.memo的優(yōu)化。因為每次父組件重新渲染時,knowledge_list都會被重新創(chuàng)建,即使它的值沒有發(fā)生變化。這樣會導致KnowledgeTab組件的props發(fā)生變化,從而觸發(fā)不必要的重新渲染。

而使用useMemo創(chuàng)建一個空數(shù)組作為默認值,可以保證在父組件重新渲染時,knowledge_list_default的引用不會發(fā)生變化,從而避免不必要的重新渲染。這樣就能夠保持React.memo的優(yōu)化效果,只有在knowledge_list的值真正發(fā)生變化時才會重新渲染KnowledgeTab組件。

所以,總結(jié)起來就是默認值如果傳給子組件,父組件每一次更新都會導致子組件更新,導致子組件的React.memo失效

拆分為狀態(tài)自治的獨立組件

當一個組件的代碼變得復雜或包含大量的子組件時,可以考慮將其中的一部分代碼抽取為一個獨立的子組件。這樣做的好處是可以將復雜的邏輯拆分為多個小組件,提高代碼的可讀性和可維護性。
同時,抽取組件也可以配合使用React.memo進行優(yōu)化。
下面是一個抽取獨立組件的例子
客戶端性能優(yōu)化實踐,前端,react.js,性能優(yōu)化文章來源地址http://www.zghlxwxcb.cn/news/detail-769157.html

import React, { memo } from 'react'
import { Tooltip } from 'antd'
import classNames from 'classnames'
import Item from './item'
import styles from '../../index.less'

interface Item {
  name: string
  id: string
}
interface CategoryProps {
  item: Item
  activeKey: string
  onClickItem: () => void
}
const Category: React.FC<CategoryProps> = props => {
  const { item, activeKey, onClickItem } = props
  const { name, id } = item

  return (
    <Tooltip
      title={name}
      placement="topRight"
      align={{
        offset: [0, 5],
      }}
    >
      <span
        key={id}
        className={classNames(styles.tab_item, {
          [styles.active_item]: activeKey === id,
        })}
        onClick={onClickItem}
      >
        {name}
      </span>
    </Tooltip>
  )
}

export default memo(Category)

到了這里,關(guān)于客戶端性能優(yōu)化實踐的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔相關(guān)法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • 基于Electron27+React18+ArcoDesign客戶端后臺管理EXE

    基于Electron27+React18+ArcoDesign客戶端后臺管理EXE

    electron-react-admin 基于electron27整合vite.js+react18搭建桌面端后臺管理程序解決方案。 前幾天有分享electron27+react18創(chuàng)建跨平臺應(yīng)用實踐,大家感興趣可以去看看。 https://blog.csdn.net/yanxinyun1990/article/details/134047329 Electron-ReactAdmin支持 暗黑/白晝 兩種主題。 技術(shù)棧 編輯器:vscode 使用技

    2024年02月08日
    瀏覽(29)
  • 獲取客戶端真實 IP 地址的最佳實踐

    1. 業(yè)務(wù)上云帶來性能收益 公司從去年全面推動業(yè)務(wù)上云,而以往 IDC 架構(gòu)部署上,接入層采用典型的 4 層 LVS 多機房容災(zāi)架構(gòu),在業(yè)務(wù)高峰時期,擴容困難(受限于物理機資源和 LVS 內(nèi)網(wǎng)網(wǎng)段的網(wǎng)絡(luò)規(guī)劃),且抵擋不住 HTTPS 卸載引發(fā)的高 CPU 占用。 而經(jīng)過壓力測試發(fā)現(xiàn),使用

    2024年02月05日
    瀏覽(30)
  • Java web應(yīng)用性能分析之客戶端慢

    Java web應(yīng)用性能分析之客戶端慢

    客戶端慢的原因包括: 終端設(shè)備老化(手機、PAD、電腦年限久遠、運行期間產(chǎn)生了很多垃圾未清除) 終端網(wǎng)絡(luò)設(shè)備老化(路由器、交換機老化) 跟我們使用的手機一樣,路由器也需要及時更新?lián)Q代,否則硬件跟不上了,再高的寬帶也帶不來流暢的網(wǎng)速。其中傳輸協(xié)議對于路

    2024年04月24日
    瀏覽(24)
  • hbase優(yōu)化:客戶端、服務(wù)端、hdfs

    hbase優(yōu)化 一.讀優(yōu)化 1.客戶端: 2.服務(wù)器: 3.列簇:是否過多、 是否使用布隆過濾器:任何業(yè)務(wù)都應(yīng)該設(shè)置Bloomfilter,通常設(shè)置為row就可以,除非確認業(yè)務(wù)隨機查詢類型為row+cf,可以設(shè)置為rowcol 是否設(shè)置ttl 4.hdfs優(yōu)化: 二、寫優(yōu)化 是否需要寫WAL?WAL是否需要同步寫入 用批量

    2024年02月14日
    瀏覽(37)
  • TCP客戶端及服務(wù)器端開發(fā)實踐

    TCP客戶端及服務(wù)器端開發(fā)實踐

    ① TCP客戶端應(yīng)用程序開發(fā) ② TCP服務(wù)器端應(yīng)用程序開發(fā) 客戶端程序是指運行在用戶設(shè)備上的程序,服務(wù)端程序是指運行在服務(wù)器設(shè)備上的程序,專門為客戶端提供數(shù)據(jù)服務(wù)。那如何記憶呢? 主動發(fā)起建立連接請求的是客戶端程序,等待接受連接請求的是服務(wù)端程序。 開發(fā)流

    2024年04月09日
    瀏覽(27)
  • 前端解決客戶端不安全隨機數(shù)

    前端項目在安全漏洞掃描的時候,爆出了客戶端不安全隨機數(shù)的問題,看了下代碼是因為使用了 Math.random() 生成隨機數(shù)造成的。 百度了一下,math.random()并不是真的隨機數(shù),而是偽隨機數(shù)! 原因 Math.random() 函數(shù)是 JavaScript 內(nèi)置的一個函數(shù),它用于生成一個 0 到 1(包括0,不包括

    2024年02月16日
    瀏覽(24)
  • 【參數(shù)匯總】mysql服務(wù)端/客戶端常見優(yōu)化參數(shù)

    1、innodb_buffer_pool_size (innodb索引buffer pool緩沖區(qū)大?。?默認大小為128M, 官方推薦其配置為系統(tǒng)內(nèi)存的 50% 到 75% 。 一般innodb_buffer_pool_size要結(jié)合以下兩個參數(shù)來設(shè)置: innodb_buffer_pool_chunk_size 從 MySQL 5.7.5 開始,我們可以動態(tài)修改 InnoDB Buffer Pool 的大小。這個新特性同時也引入

    2024年02月04日
    瀏覽(31)
  • Netty理論與實踐(二) 創(chuàng)建http客戶端 服務(wù)端

    Netty理論與實踐(二) 創(chuàng)建http客戶端 服務(wù)端

    1. 使用echo服務(wù)器模擬http 通過上一篇文章中的echo服務(wù)器程序來模擬一次HTTP請求。 接收消息的代碼如下: 我們通過postman直接訪問echo服務(wù)器: 請求成功,echo服務(wù)器接收到了本次HTTP請求,控制臺打印內(nèi)容如下: 上面的原理很容易理解,postman通過tcp建立與服務(wù)器localhost:8001的連

    2024年02月16日
    瀏覽(20)
  • 企業(yè)內(nèi)網(wǎng)終端安全無客戶端準入控制技術(shù)實踐

    企業(yè)內(nèi)網(wǎng)終端安全無客戶端準入控制技術(shù)實踐

    終端無代理/無客戶端準入控制技術(shù)因其良好的用戶體驗而倍受創(chuàng)新企業(yè)的青睞。無代理/無客戶端準入控制技術(shù),顧名思義,是一種在網(wǎng)絡(luò)中對終端實施訪問控制的方法,無需依賴特定的客戶端軟件。 不同于銀行、醫(yī)院等傳統(tǒng)行業(yè)的終端準入控制需求, 芯片半導體、生物制藥

    2024年02月12日
    瀏覽(28)
  • 關(guān)于ios客戶端與web網(wǎng)頁js交互

    iOS與JS的交互可以通過以下幾種方式實現(xiàn): 1.使用UIWebView或WKWebView加載Html頁面并在其中添加Javascript腳本,通過WebView的代理方法捕獲Javascript腳本發(fā)出的事件,從而實現(xiàn)與iOS原生代碼的交互。 2.使用JSBridge框架,它提供了一種簡單的方式在Javascript和iOS原生代碼之間進行通信。

    2024年02月10日
    瀏覽(21)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包