昂貴的DOM操作:一次DOM導致的性能問題排查記錄

公司來了一個前端實習生,踏實,勤快,很快得到老大的認可,分配給她一個需求,大概如下:構建一個公司產品的評論展示頁面,頁面可以滾動加載新的內容,同時如果已經加載的內容發生變化(比如:點贊數)也要跟新。

現象

開發完成之后,對接后端連調,由于開始連調的是測試環境,環境當中沒有很多數據,所以沒有發現問題,于是接入公司真實數據接口,發現確實很卡,尤其是滾動加載的時候,于是測試打回,對于實習生,尤其是妹子,大家開始幫忙看問題。

排查思路

確實遇到這樣的問題,總是有一套完整的流程區排查,這里分享一下我個人的習慣思路:

1. 初步癥狀確認

  • 觀察現象:頁面是否出現明顯卡頓、滾動不流暢、更新延遲

  • 用戶反饋:收集用戶關于特定頁面/操作卡頓的報告

  • 性能指標:監控FPS(幀率)、CPU占用率、內存使用情況

2. 瀏覽器工具分析

這個是我最常用的,也希望能和大家討論

Chrome DevTools 使用步驟:

  1. Performance面板錄制

    • 重現問題場景同時錄制性能時間線

    • 重點關注:

      • 長任務(Long Tasks,超過50ms的任務)

      • 頻繁的Layout(重排)和Paint(重繪)

      • 高耗時的Function Call

  2. Memory面板檢查

    • 拍攝堆快照,檢查DOM節點數量是否異常增長

    • 檢查是否有分離的DOM樹(Dettached DOM tree)內存泄漏

  3. Rendering面板

    • 開啟Paint flashing查看重繪區域

    • 開啟Layout Shift Regions查看布局偏移

    • 開啟FPS meter實時監控幀率

確定問題

自然,看了上面的參數,至少感覺我(接口端)沒有大問題,然后發現重繪(paint)比較高,所以開始看前端代碼

她的代碼大概如下:

// 不好的實現方式 - 頻繁操作DOM
function updateItems(items) {items.forEach(item => {const element = document.getElementById(`item-${item.id}`);if (element) {element.querySelector('.likes-count').textContent = item.likes;element.querySelector('.comments-count').textContent = item.comments;element.querySelector('.price').textContent = item.price;// 可能還有更多屬性更新...}});
}
?
// 數據可能來自WebSocket或定期輪詢
socket.on('item-updates', updateItems);

嗯,看到循環當中操作dom,那么肯定先懷疑dom消耗大問題,即使不是這個問題導致的,也得琢磨優化。

優化思路

確實也沒有發現別的問題,那么就開始嘗試減少dom操作,大概的思路就是檢索dom跟新,想到兩種:

1、使用文檔片段,批量插入DOM,這個需要和產品溝通,滾動同時一條一條加載如果性能沒有問題,那么用戶體驗肯定最好,但是卡了之后,用戶體驗只會更糟糕,所以滾動定長之后加載下面一頁,然后批量生成文檔片段,統一插入。

2、減少用戶操作頻率,這個自然不能要求用戶慢慢的來,那么就寄出大招,節流/防抖

所以就做了以下調整,我貼出當時我思考構建的模擬代碼:

// 更好的實現方式 - 批量更新
function updateItemsOptimized(items) {// 使用requestAnimationFrame減少重繪requestAnimationFrame(() => {// 創建文檔片段const fragment = document.createDocumentFragment();const updates = new Map();// 先收集所有需要更新的元素items.forEach(item => {const element = document.getElementById(`item-${item.id}`);if (element) {updates.set(element, item);}});// 批量處理更新updates.forEach((item, element) => {const clone = element.cloneNode(true);clone.querySelector('.likes-count').textContent = item.likes;clone.querySelector('.comments-count').textContent = item.comments;clone.querySelector('.price').textContent = item.price;fragment.appendChild(clone);});// 一次性替換updates.forEach((_, element) => {element.parentNode.replaceChild(fragment.cloneNode(true), element);});});
}
?
// 加上防抖處理
const debouncedUpdate = _.debounce(updateItemsOptimized, 100);
socket.on('item-updates', debouncedUpdate);

當然,還有高級的思路,比如VUE和React虛擬DOM或者差異化更新、requestAnimationFrame在瀏覽器重繪周期內批量處理更新、CSS硬件加速:對頻繁更新的元素使用transform/opacity等屬性,這些也琢磨的用,但是考慮到太復雜(懶),而且優化后確實好很多,就不做了,不過效果已經有了。如果大家有其他思路歡迎一起聊聊。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/75934.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/75934.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/75934.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

前端服務配置詳解:從入門到實戰

前端服務配置詳解:從入門到實戰 一、環境配置文件(.env) 1.1 基礎結構 在項目根目錄創建 .env 文件: # 開發環境 VUE_APP_API_BASE_URL http://localhost:3000/api VUE_APP_VERSION 1.0.0# 生產環境(.env.produc…

【學習筆記】計算機網絡(七)—— 網絡安全

第7章 網絡安全 文章目錄 第7章 網絡安全7.1 網絡安全問題概述7.1.1 計算機網絡面臨的安全性威脅7.1.2 安全的計算機網絡7.1.3 數據加密模型 7.2 兩類密碼體制7.2.1 對稱密鑰密碼體制7.2.2 公鑰密碼體制 7.3 鑒別7.3.1 報文鑒別7.3.2 實體鑒別 7.4 密鑰分配7.4.1 對稱密鑰的分配…

我用Cursor + DeepSeek + Claude-3.7-Sonnet + DevBox,10分鐘開發了一個系統

大家好,我是袁庭新。Cursor最近可謂是火的一塌糊涂,于是我深度體驗了一波。我用的環境是Cursor Claude-3.7-Sonnet DevBox,整個過程我一行代碼都沒有寫,10分鐘幫我開發了一個系統,且前后端聯調一把通過。驚出一身冷汗…

SpringBoot企業級開發之【用戶模塊-登錄】

開發之前我們先看一下接口文檔的要求: 開發思路: 開發實操: 因為我們之前開發注冊的時候,就有了一些相關的操作,所以在這里我們只需要定義登錄的controller即可: //用戶登錄PostMapping("/login"…

mysql 8.0.27-docker

安裝 可以略過本步 https://dev.mysql.com/downloads/https://dev.mysql.com/downloads/ 鏡像查詢與安裝 先查詢: docker search mysql 明顯會報錯 Error response from daemon: Get "https://index.docker.io/v1/search?qmysql&n25": dial tcp…

Pgvector的安裝

Pgvector的安裝 向量化數據的存儲,可以為 PostgreSQL 安裝 vector 擴展來存儲向量化數據 注意:在安裝vector擴展之前,請先安裝Postgres數據庫 vector 擴展的步驟 1、下載vs_BuildTools 下載地址: https://visualstudio.microso…

Python高階函數-sorted(深度解析從原理到實戰)

一、sorted()函數概述 sorted()是Python內置的高階函數,用于對可迭代對象進行排序操作。與列表的sort()方法不同,sorted()會返回一個新的已排序列表,而不改變原數據。 基本語法 sorted(iterable, *, keyNone, reverseFalse)二、核心參數詳…

ArcGIS Pro/GeoScene Pro AI 助手 2.1

引言 面對ArcGIS Pro/GeoScene Pro復雜的操作界面和腳本開發需求,你是否還在為功能定位、代碼調試和效率優化而煩惱?今天,推出自制的Pro AI助手2.0版本,七大核心功能將革新你的GIS工作方式!無論是界面操作指引、一鍵生…

如何將本地更改的README文件同步到自己的GitHub項目倉庫

如何將本地更改的 README 文件同步到 GitHub 倉庫 在你 git clone 下來的工程目錄下: 先使用 robocopy YOUR\SOURCE\CODE\DIR YOUR\GIT\CLONE\DIR /E /XD .git /DCOPY:T 將你的更改Copy到你git下來的工程中(上面的命令會自動處理,例如只會C…

PostIn V1.0.8版本發布,IDEA 插件支持一鍵掃描上報,讓接口定義不再繁瑣

PostIn是一款國產開源免費的接口管理工具,包含項目管理、接口調試、接口文檔設計、接口數據MOCK等模塊,支持常見的HTTP協議、websocket協議等,支持免登陸本地接口調試,同時可以對項目進行靈活的成員權限、消息通知管理等。本周Pos…

UE5學習筆記 FPS游戲制作36 UI動畫

文章目錄 目的效果創建動畫UI準備制作動畫 播放動畫目的效果創建動畫UI準備制作動畫 播放動畫注冊播放事件 目的效果 我們要創建一個提示動畫,文字先漸顯,然后向上移動,同時漸隱 創建動畫 UI準備 創建一個UI控件,然后創建一個…

HTTP 響應頭 Strict-Transport-Security 缺失漏洞

HTTP 響應頭 Strict-Transport-Security 缺失漏洞 這個漏洞就是說明網站的HTTP響應頭中沒有設置Strict-Transport-Security,沒有設置則可以通過將https自己手動改成htttp的方式進行訪問。不安全 解決方法 1.nginx配置 nginx中增加如下配置: location / …

代理模式的優缺點是什么?

什么是代理模式? 代理模式(Proxy Pattern)是一種結構型設計模式,它通過創建代理對象來控制對原始對象的訪問。 這種模式在前端開發中廣泛應用,特別是在需要控制對象訪問、添加額外邏輯或優化性能的場景中。 ??核心…

【嵌入式學習3】UDP發送端、接收端

目錄 1、發送端 2、接收端 3、UDP廣播 1、發送端 from socket import *udp_socket socket(AF_INET,SOCK_DGRAM) udp_socket.bind(("127.0.0.1",3333))data_str "UDP發送端數據" data_bytes data_str.encode("utf-8") udp_socket.sendto(d…

AI重構SEO關鍵詞精準布局

內容概要 在傳統SEO策略面臨搜索場景碎片化、用戶意圖復雜化的挑戰下,AI技術通過多維數據分析與算法建模,正在重構關鍵詞布局的邏輯框架。基于自然語言處理(NLP)的語義分析能力,AI可精準識別搜索詞背后的需求層級&…

谷歌發布網絡安全AI新模型Sec-Gemini v1

谷歌近日宣布推出實驗性AI模型Sec-Gemini v1,旨在通過人工智能技術革新網絡安全防御體系。該模型由Sec-Gemini團隊成員Elie Burzstein和Marianna Tishchenko共同研發,旨在幫助網絡安全人員應對日益復雜的網絡威脅。 攻防不對稱的破局之道 Sec-Gemini團隊…

IntelliJ IDEA下開發FPGA——FPGA開發體驗提升__下

前言 由于Quartus寫代碼比較費勁,雖然新版已經有了代碼補全,但體驗上還有所欠缺。于是使用VS Code開發,效果如下所示,代碼樣式和基本的代碼補全已經可以滿足開發,其余工作則交由Quartus完成 但VS Code的自帶的git功能&…

Python語言的需求分析

Python語言的需求分析 引言 在信息技術快速發展的今天,編程語言的選擇對于軟件開發的成功與否起著至關重要的作用。Python作為一種高級編程語言,以其簡潔易讀的語法和強大的功能受到越來越多開發者的青睞。通過對Python語言的需求分析,我們…

抓wifi無線空口包之Ubuntu抓包(二)

一、設置網卡信道和頻段,并抓包 1、使用iwconfig查看自己機器的無線網卡名稱 wangwang-ThinkCentre-M930t-N000:~$ iwconfig lo no wireless extensions. eno1 no wireless extensions. enxc8a3624ab329 no wireless extensions. wlx90de80d1b5b1 IE…

深度學習實戰電力設備缺陷檢測

本文采用YOLOv11作為核心算法框架,結合PyQt5構建用戶界面,使用Python3進行開發。YOLOv11以其高效的實時檢測能力,在多個目標檢測任務中展現出卓越性能。本研究針對電力設備缺陷數據集進行訓練和優化,該數據集包含豐富的電力設備缺…