性能優化:Vue 3 `v-memo` 指令詳解

v-memo 是 Vue 3 提供的一個性能優化工具,能幫助開發者緩存模板內容,減少不必要的渲染開銷。本文將介紹 v-memo 的引入版本、作用、使用方法和實現原理,并通過示例說明如何使用它。內容基于 Vue 3.5.18(截至 2025 年 7 月的最新版本),各位前端同胞過過眼就好。

一、v-memo 是什么?哪個版本引入?

1. 引入版本

v-memoVue 3.2.0(2021 年 8 月發布)中首次亮相,是 Vue 3 編譯器優化的新特性,專為提升渲染性能設計。

2. 作用

v-memo 用于緩存模板的子樹,通過傳入一個固定長度的依賴數組,只有當數組中的值發生變化時,包裹的 DOM 子樹才會重新渲染。其核心優勢包括:

  • 減少渲染開銷:跳過靜態或低頻變化內容的重復渲染。
  • 優化復雜場景:特別適合大型列表、表格或包含復雜計算的模板。
  • 靈活控制:相比 v-once 的完全靜態化,v-memo 能根據依賴動態決定是否更新。

它類似于 React 的 React.memo,但作用于模板片段,粒度更細,適合微優化。

適用場景

  • 靜態 UI(如頁頭、頁腳)。
  • 大型 v-for 列表(例如超過 1000 項)vue官方建議。
  • 包含耗時計算(如 computed 屬性)的模板。

二、如何使用 v-memo

1. 基本用法

v-memo 需要一個固定長度的 依賴數組(類型:any[]),只有數組中的值變化時,Vue 才會重新渲染包裹的模板內容。如果依賴不變,渲染將完全跳過,甚至虛擬 DOM 的 VNode 創建也會被省略。

<template><div v-memo="[valueA, valueB]"><!-- 只有 valueA 或 valueB 變時,這部分才會重新渲染 --><p>{{ content }}</p></div>
</template>

注意

  • 正確指定依賴數組至關重要,漏掉關鍵依賴可能導致更新被錯誤跳過。
  • 傳入空數組(v-memo="[]")等同于 v-once,模板只渲染一次。

2. 示例:優化靜態內容

以下示例展示如何用 v-memo 優化包含復雜計算的靜態內容。

<template><div><button @click="count++">點我加1:{{ count }}</button><div v-memo="[staticValue]"><p>靜態內容:{{ staticValue }}</p><p>復雜計算:{{ expensiveComputed }}</p></div></div>
</template><script setup>
import { ref, computed } from 'vue'const count = ref(0)
const staticValue = ref('固定內容')// 模擬耗時計算
const expensiveComputed = computed(() => {console.log('跑了一次復雜計算')return staticValue.value + ' - 計算結果'
})
</script><style scoped>
button {padding: 8px 16px;background: #409eff;color: white;border: none;border-radius: 4px;cursor: pointer;margin-bottom: 16px;
}
div {padding: 10px;background: #f5f5f5;border-radius: 4px;
}
</style>

運行效果

  • 點擊按鈕增加 count 會觸發父組件渲染,但因為 staticValue 未變,v-memo 包裹的 <div> 及其子內容不會重新渲染。
  • expensiveComputed 僅在初次渲染或 staticValue 變化時運行,控制臺只打印一次“跑了一次復雜計算”。

3. 示例:搭配 v-for 優化大型列表

v-memo 在渲染海量 v-for 列表時特別有用。以下示例展示如何優化列表項的渲染。

<template><div><button @click="selected = selected === 1 ? 2 : 1">切換選中:{{ selected }}</button><ul><li v-for="item in list" :key="item.id" v-memo="[item.id === selected]"><p>ID:{{ item.id }} - 選中:{{ item.id === selected }}</p><p>更多內容...</p></li></ul></div>
</template><script setup>
import { ref } from 'vue'const selected = ref(1)
const list = ref([{ id: 1, name: 'Item 1' },{ id: 2, name: 'Item 2' },{ id: 3, name: 'Item 3' },
])
</script><style scoped>
button {padding: 8px 16px;background: #409eff;color: white;border: none;border-radius: 4px;cursor: pointer;margin-bottom: 16px;
}
ul {list-style: none;padding: 0;
}
li {padding: 10px;background: #f5f5f5;border-radius: 4px;margin-bottom: 8px;
}
</style>

說明

  • 每個列表項的 v-memo="[item.id === selected]" 確保只有當 item.id === selected 的值變化時,該項才會重新渲染。
  • item.id 不需加入依賴數組,因為 Vue 會根據 :key 自動處理列表項的復用。
  • selected 變化時,只有受影響的列表項會更新,其他項復用緩存的 VNode,跳過 diff 和渲染。

4. 注意事項

  • 依賴數組準確性:依賴數組必須包含所有影響渲染的變量,否則可能導致更新被錯誤跳過。
  • v-for 的搭配v-memov-for 需綁定在同一元素上,且不能在 v-for 內部使用 v-memo
    <!-- 正確 -->
    <li v-for="item in list" :key="item.id" v-memo="[item.id === selected]">...</li>
    <!-- 錯誤 -->
    <ul v-for="item in list" :key="item.id"><li v-memo="[item.id === selected]">...</li>
    </ul>
    
  • 響應式依賴:依賴項需為 refreactivecomputed 值,確保響應式追蹤生效。
  • 子組件限制v-memo 只控制模板渲染,子組件內部邏輯可能仍需單獨優化。
  • 空依賴數組v-memo="[]" 等同于 v-once,僅渲染一次。

三、v-memo 的實現原理

1. 工作流程

v-memo 結合 Vue 3 的編譯器和響應式系統,實現高效的渲染緩存:

  1. 模板解析

    • 編譯器識別 v-memo 指令,為包裹的模板生成特殊渲染邏輯。
    • 依賴數組被解析為響應式依賴,類似 watchEffect 的依賴收集。
  2. 依賴追蹤

    • 依賴數組中的值由 Vue 3 的 Proxy 響應式系統監控。
    • 依賴變化時,Vue 標記該 DOM 子樹需要更新。
  3. VNode 緩存

    • 初次渲染生成 v-memo 包裹子樹的 VNode(虛擬 DOM 節點)。
    • 依賴不變時,Vue 復用緩存的 VNode,跳過 diff 和 DOM 更新。
  4. 更新機制

    • 依賴變化時,Vue 生成新 VNode,執行 diff 算法更新 DOM。
    • 子組件的更新邏輯不受 v-memo 控制,需單獨優化(如 defineAsyncComponent)。

2. 與 v-once 的區別

  • v-once:只渲染一次,之后完全靜態,忽略所有數據變化。
  • v-memo:根據依賴數組動態決定是否渲染,適合半靜態場景。

3. 底層細節

  • 響應式系統:依賴 Vue 3 的 Proxy 實現精確的依賴追蹤。
  • 編譯器優化:為 v-memo 節點添加 PatchFlags,運行時跳過不必要的 diff。
  • 性能提升:通過緩存 VNode 和減少 DOM 操作,顯著降低復雜場景的開銷。

四、適用場景與優化建議

1. 適用場景

  • 靜態 UI:頁頭、頁腳、固定文本。
  • 大型列表:超過 1000 項的 v-for 列表,優化未選中項的渲染。
  • 復雜計算:包裹耗時的 computed 或復雜模板邏輯。

2. 優化建議

  • 精確依賴:只列出影響渲染的變量,避免多余更新。
  • 搭配 v-for:在列表項上使用 v-memo,結合 :key 優化。
  • 其他優化手段
    • defineAsyncComponent 異步加載子組件。
    • 大數據量場景搭配虛擬列表(如 vue-virtual-scroller)。
    • 使用 keep-alive 緩存動態組件。
  • 調試技巧:用控制臺日志檢查依賴變化,確保 v-memo 行為符合預期。

3. 局限性

  • 子組件更新v-memo 只管模板,子組件邏輯需單獨優化。
  • 依賴管理:依賴數組不準確可能導致更新丟失,需仔細設計。
  • 適用范圍:頻繁變化的場景中,v-memo 的緩存效果有限。

五、總結

  • 版本v-memo 從 Vue 3.2.0 開始支持。
  • 作用:緩存模板子樹,僅在依賴變化時更新,優化性能。
  • 用法:用 v-memo="[dep1, dep2]" 包裹模板,指定依賴。
  • 原理:結合 Vue 3 編譯器和響應式系統,緩存 VNode,跳過不必要的 diff。

v-memo 是 Vue 3 的性能優化利器,適合處理靜態或低頻變化的模板,尤其在大型列表或復雜計算場景下效果顯著。合理選擇依賴,結合其他優化手段,能讓項目更高效。

點個收藏,關注前端結城,一起用代碼點亮前端世界!🚀

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

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

相關文章

標準庫開發和寄存器開發的區別

1.標準庫void GPIO_Toggle_INIT(void)//初始化GPIO {GPIO_InitTypeDef GPIO_InitStructure {0};//定義GPIO結構體RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);//使能GPIO時鐘GPIO_InitStructure.GPIO_Pin GPIO_Pin_2;//GPIO引腳選擇GPIO_InitStructure.GPIO_Mode …

在 WebSocket 中使用 @Autowired 時遇到空指針異常

背景&#xff1a;在websocket在有新的連接加入進來時&#xff0c;調用servier中的服務&#xff0c;使用 Autowired 注入的 Bean 竟然是 null&#xff01;這并非 Spring 的 Bug&#xff0c;而是對 WebSocket 生命周期管理理解不足導致的。了解這個問題&#xff0c;我們需要區分兩…

MGER實驗

一、實驗拓撲圖二、配置1.R5為ISP&#xff0c;只能進行IP地址配置&#xff0c;其所有地址均配為公有IP地址R1側為15.1.1.1&#xff0c;對應R5為15.1.1.2R2側為25.1.1.2&#xff0c;對應R5為25.1.1.1R3側為35.1.1.2&#xff0c;對應R5為35.1.1.1R4側為45.1.1.2&#xff0c;對應R…

基于 XGBoost 與 SHAP 的醫療自動化辦公與可視化系統(下)

— 登錄接口 — @app.post(“/token”) def login(form_data: OAuth2PasswordRequestForm = Depends()): user = fake_users_db.get(form_data.username) if not user or form_data.password != user[“password”]: raise HTTPException(status_code=400, detail=“用戶名或密…

python學智能算法(二十九)|SVM-拉格朗日函數求解中-KKT條件

引言 前序學習進程中&#xff0c;對拉格朗日函數執行了初步求導&#xff0c;并獲得了簡化后的拉格朗日函數極值計算式&#xff1a; L(w,b,α)∑i1mαi?12∑i,j1mαiαjyiyjxiTxjL(w,b,\alpha)\sum_{i1}^{m}\alpha_{i}-\frac{1}{2}\sum_{i,j1}^{m}\alpha_{i}\alpha_{j}y_{i}y_…

【AI論文】MiroMind-M1:通過情境感知多階段策略優化實現數學推理的開源新進展

摘要&#xff1a;近期&#xff0c;大型語言模型已從流暢的文本生成發展至能在多個領域進行高級推理&#xff0c;由此催生了推理語言模型&#xff08;RLMs&#xff09;。在眾多領域中&#xff0c;數學推理堪稱代表性基準&#xff0c;因為它需要精確的多步驟邏輯與抽象推理能力&a…

《使用Qt Quick從零構建AI螺絲瑕疵檢測系統》——6. 傳統算法實戰:用OpenCV測量螺絲尺寸

目錄一、概述1.1 背景介紹&#xff1a;從“看見”到“看懂”1.2 學習目標二、圖像預處理&#xff1a;讓目標更突出三、輪廓發現與尺寸測量四、總結與展望一、概述 1.1 背景介紹&#xff1a;從“看見”到“看懂” 在上一篇文章中&#xff0c;我們成功地為應用程序安裝了“眼睛…

《人性的弱點》重構【01】

手上有本《人性的弱點》&#xff08;韓文橋 譯&#xff0c;浙江文藝出版社&#xff0c;2017.1出版&#xff09;&#xff0c;前些年買的&#xff0c;近期翻出來看看。這門書雖成書于80多年前&#xff0c;但卡耐基對人性洞察之深刻&#xff0c;時至今日&#xff0c;并未覺得過時。…

k8s開啟審計日志

k8s默認是關閉審計功能的&#xff0c;想看的話需要到apiserver的pod中才可以。 開啟此功能是為了進行k8s審計日志的收集&#xff0c;方便我們查看k8s中用戶的各自操作。 開啟此功能之前&#xff0c;我們要先創建個審計策略文件audit-policy.yaml 例如以下的測驗文件 apiVersion…

Kafka MQ 消費者應用場景

Kafka MQ 消費者應用場景 1 消費者自動提交的時機 在 Kafka 中默認的消費位移的提交方式是自動提交,這個由消費者客戶端參數 enable.auto.commit 配置,默認值為 true。當然這個默認的自動提交不是每消費一條消息就提交一次,而是定期提交,這個定期的周期時間由客戶端參數 …

Git版本控制系統

Git作為目前最流行的分布式版本控制系統&#xff0c;已經成為開發者必備的技能之一。本文將全面介紹Git的核心概念、基本操作、分支管理以及與GitHub的協作開發&#xff0c;幫助讀者從零開始掌握Git的使用。 一、Git概述 1.1 Git發展歷史 Git誕生于2005年&#xff0c;由Linu…

如何編譯RustDesk(Unbuntu 和Android版本)

編譯Linux版本的RustDesk備注&#xff1a;官方文檔上&#xff0c;一邊都是基于sciter&#xff0c;這個在后面已經不建議使用了&#xff0c;但是依然可以編譯剛開始的時候看官方的文檔&#xff0c;涉及的東西比較多&#xff0c;也搞的一頭霧水&#xff0c;通過B站上一個視頻&…

Spring中的循環依賴:解密、破局與架構啟示

> 當兩個Bean緊緊相擁,Spring容器卻陷入死鎖——這是Java開發者的經典噩夢 某電商平臺凌晨上線時突然宕機,日志里反復滾動著`BeanCurrentlyInCreationException`的報錯。經排查,**優惠券服務與庫存服務在初始化時相互依賴**,形成致命閉環。這個價值百萬的故障案例,揭開…

DataFrame?(數據框)

一種二維表格型數據結構&#xff0c;類似于電子表格&#xff08;如 Excel&#xff09;或 SQL 表&#xff0c;由行&#xff08;記錄&#xff09;?和列&#xff08;字段&#xff09;?組成。它是數據分析、機器學習和科學計算中最常用的數據結構之一&#xff0c;尤其在 ?Python…

B站視頻評論數據爬取

爬取B站視頻評論數據爬取與分析 如果只要單純的腳本可以直接看項目結構里的b_comments.py 一、技術架構 1、環境配置 Python 3.8PyCharm 2、模塊配置 requests&#xff1a;用于發送HTTP請求time&#xff1a;用于處理時間相關的操作csv&#xff1a;用于讀寫CSV文件json&#xff…

OpenAI最新大模型GPT-4o體驗之Code Copilot AI編程大模型

一、前言GPT-4o&#xff08;"o"代表"全能"&#xff09;具備處理各種文本、聲音和圖像資料的能力&#xff0c;能夠輸出多種格式的文本、聲音和圖像。GPT-4o 的推出標志著 AI 技術的重大突破。它不再局限于單一媒介&#xff0c;而是首次實現了文本、語音和圖…

社交電商推客系統全棧開發指南:SpringCloud+分潤算法+Flutter跨端

一、推客系統概述與市場背景推客系統&#xff08;TuiKe System&#xff09;是一種基于社交關系的營銷推廣平臺&#xff0c;通過用戶分享商品或服務鏈接&#xff0c;實現裂變式傳播和精準營銷。近年來&#xff0c;隨著社交電商的蓬勃發展&#xff0c;推客系統已成為企業獲客的重…

網安-中間件-Redis未授權訪問漏洞

目錄 Redis Redis持久化 動態修改配置 使用反彈連接的情況 常見監聽端口的方式 常見建立反彈連接的方式 流程 Linux crontab cron文件存儲路徑 利用Redis實現攻擊 1.webshell提權案例 2.定時任務shell反彈案例 3.SSH Key getshell案例 ?編輯Redis其他利用方式 …

【c++深入系列】:萬字詳解棧和隊列和deque(附模擬實現的源碼)

&#x1f525; 本文專欄&#xff1a;c &#x1f338;作者主頁&#xff1a;努力努力再努力wz &#x1f4aa; 今日博客勵志語錄&#xff1a; 石頭能被水滴穿&#xff0c;不是因為水有多強&#xff0c;而是因為它從未停過。 ★★★ 本文前置知識&#xff1a; 模版 棧 那么棧這個…

速通python加密之RSA加密

RSA加密 RSA加密是一種非對稱加密算法&#xff08;與AES等對稱加密不同&#xff09;&#xff0c;由羅納德李維斯特&#xff08;Ron Rivest&#xff09;、阿迪薩莫爾&#xff08;Adi Shamir&#xff09;和倫納德阿德曼&#xff08;Leonard Adleman&#xff09;于1977年提出&…