手寫 Vue 中虛擬 DOM 到真實 DOM 的完整過程

目錄

一、虛擬 DOM 的核心概念

二、虛擬 DOM 到真實 DOM 的流程

三、手寫虛擬 DOM 到真實 DOM 的實現

1. 定義虛擬 DOM 的結構(VNode)?

?2. 創建虛擬 DOM 轉真實 DOM 的函數

?3. 掛載虛擬 DOM 到頁面

?4. 更新虛擬 DOM 的過程(Diff 算法簡化版)

四、完整示例:虛擬 DOM 到真實 DOM 的生命周期

五、總結


一、虛擬 DOM 的核心概念

虛擬 DOM 是用 JavaScript 對象(VNode)模擬真實 DOM 結構的輕量級抽象。它的核心作用是:

  1. 減少直接操作真實 DOM 的次數:通過對比新舊虛擬 DOM 樹的差異(Diff 算法),僅更新變化的部分。
  2. 聲明式編程:開發者只需關注數據邏輯,無需手動操作 DOM。
  3. 跨平臺能力:虛擬 DOM 可用于 Web、移動端(如 Weex)或服務端渲染(SSR)

?

二、虛擬 DOM 到真實 DOM 的流程

Vue 的渲染流程可分為以下步驟:

  1. 模板編譯:將模板(<template>)編譯為渲染函數(render function)。
  2. 生成虛擬 DOM 樹:通過?render?函數返回一個虛擬 DOM 樹(由 VNode 節點組成)。
  3. 首次掛載:將虛擬 DOM 樹轉化為真實 DOM 并渲染到頁面。
  4. 數據更新:生成新的虛擬 DOM 樹,與舊樹進行 Diff 算法比較。
  5. 局部更新:將差異部分應用到真實 DOM 上(Patch 過程)。

三、手寫虛擬 DOM 到真實 DOM 的實現

以下是一個簡化版的實現示例,涵蓋虛擬 DOM 的創建、掛載和更新過程。

1. 定義虛擬 DOM 的結構(VNode)?
// VNode 結構
const vnode = {tag: 'div',          // 標簽名props: { id: 'app' }, // 屬性children: [          // 子節點{tag: 'p',props: { class: 'text' },children: ['Hello, Vue!']}]
};
?2. 創建虛擬 DOM 轉真實 DOM 的函數
// 將虛擬 DOM 轉換為真實 DOM
function createDom(vnode) {const { tag, props, children } = vnode;const dom = document.createElement(tag); // 創建真實 DOM 元素// 設置屬性if (props && typeof props === 'object') {updateProps(dom, props);}// 處理子節點if (Array.isArray(children)) {reconcileChildren(children, dom);}return dom;
}// 設置屬性
function updateProps(dom, props) {for (const key in props) {if (key === 'style') {// 處理 style 屬性for (const styleKey in props.style) {dom.style[styleKey] = props.style[styleKey];}} else {// 處理其他屬性(id、class 等)dom[key] = props[key];}}
}// 遞歸處理子節點
function reconcileChildren(children, dom) {for (const child of children) {const childDom = createDom(child); // 遞歸創建子節點dom.appendChild(childDom);}
}

?

?3. 掛載虛擬 DOM 到頁面
// 將虛擬 DOM 掛載到容器
function render(vnode, container) {const dom = createDom(vnode); // 生成真實 DOMcontainer.appendChild(dom);   // 掛載到頁面
}// 示例:將虛擬 DOM 掛載到 #root 容器
const root = document.getElementById('root');
render(vnode, root);
?4. 更新虛擬 DOM 的過程(Diff 算法簡化版)
// 比較新舊虛擬 DOM 樹并更新真實 DOM
function patch(oldVnode, newVnode, parentDom) {// 如果節點類型不同,直接替換if (oldVnode.tag !== newVnode.tag) {parentDom.replaceChild(createDom(newVnode), oldVnode.elm);return;}// 獲取真實 DOMconst elm = (newVnode.elm = oldVnode.elm);// 更新屬性updateProps(elm, oldVnode.props, newVnode.props);// 遞歸比較子節點patchChildren(oldVnode.children, newVnode.children, elm);
}// 更新屬性
function updateProps(dom, oldProps, newProps) {// 移除舊屬性for (const key in oldProps) {if (!newProps[key]) {dom[key] = null;}}// 更新或新增屬性for (const key in newProps) {if (key === 'style') {for (const styleKey in newProps.style) {dom.style[styleKey] = newProps.style[styleKey];}} else {dom[key] = newProps[key];}}
}// 遞歸比較子節點
function patchChildren(oldChildren, newChildren, parentDom) {// 簡化版:逐個比較子節點const maxLength = Math.max(oldChildren.length, newChildren.length);for (let i = 0; i < maxLength; i++) {const oldChild = oldChildren[i];const newChild = newChildren[i];if (oldChild && newChild) {patch(oldChild, newChild, parentDom);} else if (newChild) {// 新增節點parentDom.appendChild(createDom(newChild));} else if (oldChild) {// 刪除節點parentDom.removeChild(oldChild.elm);}}
}

四、完整示例:虛擬 DOM 到真實 DOM 的生命周期

<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><title>手寫 Vue 虛擬 DOM</title>
</head>
<body><div id="root"></div><script>// 1. 初始虛擬 DOMconst initialVnode = {tag: 'div',props: { id: 'app' },children: [{tag: 'p',props: { class: 'text' },children: ['Hello, Vue!']}]};// 2. 掛載初始虛擬 DOMconst root = document.getElementById('root');const initialDom = createDom(initialVnode);root.appendChild(initialDom);// 3. 模擬數據更新后的新虛擬 DOMconst newVnode = {tag: 'div',props: { id: 'app' },children: [{tag: 'p',props: { class: 'text updated' },children: ['Hello, Vue! Updated!']}]};// 4. 更新虛擬 DOM 到真實 DOMpatch(initialVnode, newVnode, root);</script>
</body>
</html>

五、總結

通過上述實現,我們可以看到 Vue 虛擬 DOM 的核心原理:

  1. 虛擬 DOM 是 JavaScript 對象:通過?createDom?函數將虛擬 DOM 轉化為真實 DOM。
  2. Diff 算法是性能優化的關鍵:通過比較新舊虛擬 DOM 樹的差異,僅更新變化的部分。
  3. 局部更新減少重排/重繪成本:避免了直接操作真實 DOM 的高昂代價。

在實際開發中,Vue 的虛擬 DOM 實現更為復雜(如處理組件、事件綁定等),但核心思想一致。掌握虛擬 DOM 的原理,不僅能幫助我們更好地理解 Vue 的運行機制,還能在性能優化和跨平臺開發中游刃有余。

?

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

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

相關文章

jmm--volatile

指令重排基礎概念 在現代處理器和編譯器為了提高程序執行效率&#xff0c;會對指令進行優化&#xff0c;其中一種優化方式就是指令重排序。在單線程環境下&#xff0c;指令重排序不會影響最終執行結果&#xff0c;因為處理器和編譯器會保證重排序后的執行結果與按照代碼順序執行…

【硬件開發】濾波電容的選擇:原理、計算與多電壓值應用實踐

濾波電容的選擇&#xff1a;原理、計算與多電壓值應用實踐 1. 引言 在現代電子系統中&#xff0c;穩定的電源供應是保證電路可靠運行的基礎。然而&#xff0c;電源線上往往不可避免地存在各種噪聲和紋波&#xff0c;這些干擾可能源自電源本身&#xff08;如整流后的脈動直流&…

【seismic unix數據生成-unif2】

Seismic Unix簡介 Seismic Unix&#xff08;SU&#xff09;是由科羅拉多礦業學院&#xff08;Colorado School of Mines&#xff09;開發的開源地震數據處理軟件包&#xff0c;專為地震勘探數據分析和研究設計。它提供了一系列命令行工具&#xff0c;支持從數據加載、處理到可…

【逆向思考 并集查找】P2391 白雪皚皚|省選-

本文涉及知識點 C并集查找 P2391 白雪皚皚 題目背景 “柴門聞犬吠&#xff0c;風雪夜歸人”&#xff0c;冬天&#xff0c;不期而至。千里冰封&#xff0c;萬里雪飄。空中刮起了鴨毛大雪。雪花紛紛&#xff0c;降落人間。 美能量星球&#xff08;pty 在 spore 上的一個殖民地…

一文講清楚React中setState的使用方法和機制

文章目錄 一文講清楚React中setState的使用方法和機制1. setState是什么2. setState方法詳解2.1 setState參數詳解2.2 setState同步異步問題2.2.1 setState異步更新2.2.2 setState同步更新 一文講清楚React中setState的使用方法和機制 1. setState是什么 React中&#xff0c;…

01_軟件卓越之道:功能性與需求滿足

引言 在軟件的世界里&#xff0c;功能性是產品與用戶之間的第一橋梁。一個軟件即使擁有華麗的界面和極致的性能&#xff0c;如果不能解決用戶的核心需求&#xff0c;也終將被市場淘汰。本文將深入探討如何確保軟件的功能性與用戶需求完美契合。 1. 需求理解&#xff1a;從模糊…

StarRocks × Tableau 連接器完整使用指南 | 高效數據分析從連接開始

一、導語&#xff1a;為什么選擇 StarRocks Tableau 連接器&#xff1f; 在當今數據驅動的商業環境中&#xff0c;企業不僅需要一個能夠處理海量數據的高性能分析數據庫&#xff0c;還需要一個直觀、強大的可視化工具來解讀數據背后的故事。StarRocks 作為新一代極速全場景 MP…

基于 SpringBoot+VueJS 助農生鮮銷售系統設計與實現7000字論文實現

摘要本論文設計并實現了一個基于 SpringBoot 和 VueJS 的助農生鮮銷售系統。系統采用前后端分離架構&#xff0c;前端使用 VueJS 框架實現用戶界面&#xff0c;后端使用 SpringBoot 框架構建服務&#xff0c;通過 MyBatis 實現數據持久化。系統實現了農產品展示、在線購物、訂單…

Pytest 測試發現機制詳解:自動識別測試函數與模塊

概述 在編寫自動化測試時,如何讓 Pytest 自動找到你的測試代碼 是一個非常基礎但重要的問題。Pytest 通過其強大的 測試發現(Test Discovery)機制,能夠自動掃描項目目錄、識別測試模塊和測試函數,從而大大簡化了測試流程。 本文將為你詳細講解 Pytest 的測試發現機制,包…

MySQL 時間日期函數

時間日期類型 MySQL中主要支持以下幾種時間日期類型&#xff1a; DATE - 日期類型 格式&#xff1a;YYYY-MM-DD范圍&#xff1a;1000-01-01 到 9999-12-31示例&#xff1a;2023-05-20 TIME - 時間類型 格式&#xff1a;HH:MM:SS范圍&#xff1a;-838:59:59 到 838:59:59示例&…

408第三季part2 - 計算機網絡 - 物理層

理解 這里有8個波形&#xff0c;每個波形代表一個馬原&#xff0c;一個馬原代表多個比特&#xff0c;這里3個比特 求波特率就直接2W 求比特率就要乘log2V 這塊記兩公式就行&#xff0c;一個下面一個上面 題目 4個相位加4種幅度就是有16種波形 這里無噪聲就是奈奎斯特定理 這…

iOS 集成RN Installing glog (0.3.5)報錯的解決方案

在集成執行RN bundle exec pod install 命令到Installing glog (0.3.5)時報錯,報錯信息如下: Installing glog (0.3.5) [!] /bin/bash -c set -e #!/bin/bash # Copyright (c) Facebook, Inc. and its affiliates. # # This source code is licensed under the MIT license …

【進階篇-消息隊列】——MQTT協議如何支持海量的在線IoT設備

目錄 一、什么是IoT二、MQTT 和其他消息隊列的傳輸協議有什么不同三、如何選擇 MQTT 產品四、MQTT 集群如何支持海量在線的 IoT 設備五、總結本文來源:極客時間vip課程筆記 一、什么是IoT IoT,也就是物聯網,物聯網這個詞兒,它的含義還不那么直觀,但你看它的英文:IoT,也就…

Chat Model API

聊天模型API為開發人員提供了將人工智能聊天完成功能集成到應用程序中的能力。它利用預訓練的語言模型&#xff0c;如GPT&#xff08;生成預訓練轉換器&#xff09;&#xff0c;以自然語言對用戶輸入生成類似人類的響應。 API通常通過向人工智能模型發送提示或部分對話來工作&…

【黑群暉】自組硬件/舊電腦nas改造(三)——使用Jellyfin創建家庭影音庫

一、打開套件中心安裝Jellyfin套件 如果找不到Jellyfin套件&#xff0c;需要手動添加三方套件源&#xff1a; 《群暉NAS必學技能&#xff1a;一鍵解鎖三方套件源&#xff0c;PT下載影音播放全搞定&#xff01;》 二、配置Jellyfin 訪問http://群暉IP:8096 進入Jellyfin初始化界…

泰山派編譯debian報錯 lb config: unrecognized option ‘--debootstrap-options‘

簡介 最近在編譯泰山派 編譯buildroot系統正常&#xff0c;但是編譯debian時總是報錯說lb 找不到一些參數&#xff0c;如下圖所示&#xff0c;應該當前的版本較低 不支持這些參數&#xff0c;我試了很多方法 升級次版本 但是提示的是最新的&#xff0c;最后經過一番搜索 在官方…

跨境證券交易系統合規升級白皮書:全鏈路微秒風控+開源替代,護航7月程序化交易新規落地

1 行業變革&#xff1a;四重驅動力重塑證券交易系統 當前全球證券行業正處于深刻變革期&#xff0c;跨境金融活動面臨前所未有的機遇與挑戰。今日央行開展的1310億元7天期逆回購操作&#xff0c;以及國家外匯管理局向合格境內機構投資者(QDII)新增發放30.8億美元投資額度等政策…

Node.js核心API(fs篇)

前言&#xff1a;在Node.js生態系統中&#xff0c;文件系統操作是后端開發不可或缺的一部分。fs模塊作為Node.js核心API的重要組成部分&#xff0c;提供了與文件系統交互的能力&#xff0c;涵蓋了從基礎的文件讀寫到復雜的目錄操作等功能。現代JavaScript開發中&#xff0c;處理…

HarmonyOS學習2---Stage模型

1、工程目錄結構 1.1、入口 UIAbility 1.2、入口page 1.3、配置文件 1、配置文件 1&#xff09;應用級配置文件 --- app.json5 2&#xff09;模塊級配置文件 --- module.json5 3、oh-package.json5 4、資源文件 1&#xff09;element目錄 2&#xff09;media目錄 3&#xff09…

【軟件工程】軟件復刻項目的完整流程指南

軟件復刻項目的完整流程指南 第一章、概述 一、前期準備&#xff1a;明確目標與合規性 1. 法律風險評估 版權排查&#xff1a;確認目標軟件的 UI 設計、代碼、商標是否受保護&#xff08;如界面元素、核心算法是否申請專利&#xff09;。規避侵權&#xff1a;避免直接復制 …