vue 中的數據代理

在 Vue 中,數據代理(Data Proxy) 是 Vue 實現 MVVM 模式 的關鍵技術之一。Vue 使用數據代理讓你可以通過 this.message 訪問 data.message,而不需要寫 this.data.message —— 這大大簡化了模板和邏輯代碼。

我們來深入理解它的本質、實現原理和源碼體現。

🔹 什么是數據代理?

Vue 實例將 data、props、computed 等屬性“代理”到 vm(Vue 實例)自身上,從而讓我們能直接通過 this.xx 訪問,而不必每次訪問 this._data.xx。

? 示例:數據代理的使用效果

const vm = new Vue({data: {message: 'hello'}
})console.log(vm.message) // 實際上是 vm._data.message

🧠 數據代理的實現原理(以 Vue 2 為例)

Vue 2 中通過 Object.defineProperty 實現數據代理。

👉 源碼簡化模擬:

function proxy(target, sourceKey, key) {Object.defineProperty(target, key, {get() {return target[sourceKey][key]},set(val) {target[sourceKey][key] = val}})
}

Vue 實例化時,會遍歷 data 中的所有屬性,調用 proxy(vm, ‘_data’, key) 將它們掛載到實例 vm 上。

🔧 Vue 2 中相關源碼(core/instance/state.js)

function initData(vm) {const data = vm.$options.datavm._data = typeof data === 'function' ? data.call(vm, vm) : data || {}// 數據代理const keys = Object.keys(vm._data)let i = keys.lengthwhile (i--) {proxy(vm, '_data', keys[i])}observe(vm._data)
}

📌 Vue 3 的處理方式

Vue 3 中由于響應式改為使用 Proxy,所以數據代理并不是必須通過 defineProperty 顯式定義,而是由 reactive() 和 ref() 本身提供的響應式代理能力。

import { reactive } from 'vue'const state = reactive({ count: 0 })console.log(state.count) // 已被代理,無需顯式掛載到組件實例上

Vue 3 更加模塊化,組件實例并不自動把數據代理到 this 上,尤其在

🧠 為什么要用數據代理?

簡化訪問:

  • 不用寫 this._data.xxx,直接 this.xxx

實現雙向綁定:

  • v-model 語法簡潔,背后依賴于代理 + 響應式

方便調試和語法提示:

  • IDE 能提示實例屬性;不用深層嵌套對象路徑

🔄 數據代理 vs 響應式代理

特性數據代理響應式代理
實現技術Object.defineProperty(Vue 2)Proxy(Vue 3)
目的讓你能通過 this.key 訪問 data.key追蹤依賴、觸發視圖更新
是否雙向綁定否,單純轉發 getter/setter是,配合響應式系統自動更新視圖
使用位置Vue 實例、組件所有響應式狀態(ref、reactive)

? 小結

  • 數據代理是為了簡化訪問方式,不是響應式的根本機制。
  • Vue 2 中通過 Object.defineProperty 將 data 的屬性代理到 Vue 實例上。
  • Vue 3 中響應式是通過 Proxy 實現,數據代理的需求被弱化(但原理仍然存在)。
  • 它是 MVVM 中 ViewModel 作為橋梁的一部分。

小型 Vue 響應式系統(含數據代理)

// 1. 數據代理
function proxy(vm, sourceKey, key) {Object.defineProperty(vm, key, {get() {return vm[sourceKey][key]},set(val) {vm[sourceKey][key] = val}})
}// 2. 響應式轉換(核心 Observer)
function defineReactive(obj, key, val) {const dep = new Dep()Object.defineProperty(obj, key, {get() {dep.depend()return val},set(newVal) {val = newValdep.notify()}})
}// 3. 對整個 data 對象做響應式處理
function observe(obj) {Object.keys(obj).forEach(key => defineReactive(obj, key, obj[key]))
}// 4. 依賴收集器
class Dep {constructor() {this.subscribers = new Set()}depend() {if (activeEffect) {this.subscribers.add(activeEffect)}}notify() {this.subscribers.forEach(effect => effect())}
}let activeEffect = null
function watchEffect(effect) {activeEffect = effecteffect() // 立即執行一次activeEffect = null
}// 5. 模擬 Vue 實例
function Vue(options) {this._data = options.dataobserve(this._data)// 代理 _data 到 thisObject.keys(this._data).forEach(key => {proxy(this, '_data', key)})
}
// 創建 Vue 實例
const vm = new Vue({data: {message: 'Hello',count: 1}
})// 綁定“視圖更新”邏輯
watchEffect(() => {console.log('視圖更新:', vm.message, vm.count)
})// 修改數據,自動觸發“視圖更新”
vm.message = 'Hello Vue'
vm.count++

Vue 3 響應式系統簡易實現(模擬核心功能)

// 1. 依賴收集器
const targetMap = new WeakMap()
let activeEffect = nullfunction track(target, key) {if (!activeEffect) returnlet depsMap = targetMap.get(target)if (!depsMap) {depsMap = new Map()targetMap.set(target, depsMap)}let deps = depsMap.get(key)if (!deps) {deps = new Set()depsMap.set(key, deps)}deps.add(activeEffect)
}function trigger(target, key) {const depsMap = targetMap.get(target)if (!depsMap) returnconst deps = depsMap.get(key)if (deps) {deps.forEach(effect => effect())}
}// 2. 創建響應式對象
function reactive(target) {return new Proxy(target, {get(obj, key) {track(obj, key)return Reflect.get(obj, key)},set(obj, key, value) {const result = Reflect.set(obj, key, value)trigger(obj, key)return result}})
}// 3. 注冊副作用(自動運行函數)
function effect(fn) {activeEffect = fnfn()activeEffect = null
}
const state = reactive({count: 0,name: 'Vue3'
})effect(() => {console.log('視圖更新:', state.count, state.name)
})state.count++     // 觸發更新
state.name = 'Vue3 Proxy'

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

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

相關文章

基于Python的網絡電子書閱讀系統

標題:基于Python的網絡電子書閱讀系統 內容:1.摘要 隨著數字化閱讀的興起,網絡電子書閱讀需求日益增長。本研究旨在開發一個基于Python的網絡電子書閱讀系統,以滿足用戶便捷閱讀電子書的需求。采用Python的Flask框架搭建Web服務器,結合SQLit…

基于SpringBoot的抽獎系統測試報告

一、編寫目的 本報告為抽獎系統測試報告,本項目可用于團體抽獎活動,包括了用戶注冊,用戶登錄,修改獎項以及抽獎等功能。 二、項目背景 抽獎系統采用前后端分離的方法來實現,同時使用了數據庫來存儲相關的數據&…

Apache Flink 與 Flink CDC:概念、聯系、區別及版本演進解析

Apache Flink 與 Flink CDC:概念、聯系、區別及版本演進解析 在實時數據處理和流式計算領域,Apache Flink 已成為行業標桿。而 Flink CDC(Change Data Capture) 作為其生態中的重要組件,為數據庫的實時變更捕獲提供了強大的能力。 本文將從以下幾個方面進行深入講解: 什…

單片機-STM32部分:9、定時器

飛書文檔https://x509p6c8to.feishu.cn/wiki/A749wx8T0ioqfgkzZKlc9poknUf SMT32F1系列共有8個定時器: 基本定時器(TIM6、TIM7) 通用定時器(TIM2、TIM3、TIM4、TIM5) 高級定時器(TIM1、TIM8&#xff09…

uniapp-商城-51-后臺 商家信息(logo處理)

前面對頁面基本進行了梳理和說明,特別是對驗證規則進行了闡述,并對自定義規則的兼容性進行了特別補充,應該說是干貨滿滿。不知道有沒有小伙伴已經消化了。 下面我們繼續前進,說說頁面上的logo上傳組件,主要就是uni-fil…

ideal創建Springboot項目(Maven,yml)

以下是使用 IntelliJ IDEA 創建基于 Maven 的 Spring Boot 項目并使用 YAML 配置文件的詳細步驟: 一、創建 Spring Boot 項目 啟動項目創建向導 打開 IntelliJ IDEA,點擊“File”->“New”->“Project”。 在彈出的“New Project”窗口中&#…

MATLAB中矩陣和數組的區別

文章目錄 前言環境配置1. 數據結構本質2. 運算規則(1)基本運算(2)特殊運算 3. 函數與操作4. 高維支持5. 創建方式 前言 在 MATLAB 中,矩陣(Matrix) 和 數組(Array) 的概…

iTwin 數據報表(只是簡單的原型不代表實現)

大概想法是 前端從schema和class中選中感興趣的property內容生成ecsql語句傳遞給后端后端解析ecsql并提供公開接口給各個分析工具,如excel,poewerBI等(Odata或者直接選擇來自網站)再由分析工具做進一步的處 還未想好的點 如何存…

Spring AI 系列——使用大模型對文本內容分類歸納并標簽化輸出

原理概述 利用大語言模型(LLM)實現文本分類,核心思想是通過預訓練模型理解輸入文本的語義,并將其映射到預先定義好的分類標簽。在這個過程中,我們借助 Spring AI Alibaba 提供的能力,使用阿里云 DashScope…

LeetCode 高頻題實戰:如何優雅地序列化和反序列化字符串數組?

文章目錄 摘要描述題解答案題解代碼分析編碼方法解碼方法 示例測試及結果時間復雜度空間復雜度總結 摘要 在分布式系統中,數據的序列化與反序列化是常見的需求,尤其是在網絡傳輸、數據存儲等場景中。LeetCode 第 271 題“字符串的編碼與解碼”要求我們設…

GitHub打開緩慢甚至失敗的解決辦法

在C:\Windows\System32\drivers\etc的hosts中增加如下內容: 20.205.243.166 github.com 199.59.149.236 github.global.ssl.fastly.net185.199.109.153 http://assets-cdn.github.com 185.199.108.153 http://assets-cdn.github.com 185.199.110.153 http://asset…

重生之我在2024學Fine-tuning

一、Fine-tuning(微調)概述 Fine-tuning(微調)是機器學習和深度學習中的一個重要概念,特別是在預訓練模型的應用上。它指的是在模型已經通過大量數據訓練得到一個通用的預訓練模型后,再針對特定的任務或數據…

計算機網絡 4-2-1 網絡層(IPv4)

2 IPv4分組 各協議之間的關系 IP協議(Internet Protocol, 網際協議)是互聯網的核心&#xff01; ARP協議用于查詢同一網絡中的<主機IP地址&#xff0c;MAC地址>之間的映射關系 ICMP協議用于網絡層實體之間相互通知“異常事件” IGMP協議用于實現IP組播 2.1 結構<首…

Docker中運行的Chrome崩潰問題解決

問題 各位看官是否在 Docker 容器中的 Linux 桌面環境&#xff08;如Xfce&#xff09;上啟動Chrome &#xff0c;遇到了令人沮喪的頻繁崩潰問題&#xff1f;尤其是在打開包含圖片、視頻的網頁&#xff0c;或者進行一些稍復雜的操作時&#xff0c;窗口突然消失&#xff1f;如果…

K8S cgroups詳解

以下是 Kubernetes 中 cgroups&#xff08;Control Groups&#xff09; 的詳細解析&#xff0c;涵蓋其核心原理、在 Kubernetes 中的具體應用及實踐操作&#xff1a; 一、cgroups 基礎概念 1. 是什么&#xff1f; cgroups 是 Linux 內核提供的 資源隔離與控制機制&#xff0c…

javaer快速從idea轉戰vscode

插件安裝列表 在插市場安裝下面插件 Extension Pack for JavaSpring Boot Tools 配置文件提示Database Client Database/No-SQL管理工具httpYac - Rest Client .http文件編輯、API測試工具 https://httpyac.github.io/guide/request.htmlGit Graph 圖形化Git工具XML by Red H…

[項目總結] 抽獎系統項目技術應用總結

&#x1f338;個人主頁:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 &#x1f3f5;?熱門專欄: &#x1f9ca; Java基本語法(97平均質量分)https://blog.csdn.net/2301_80050796/category_12615970.html?spm1001.2014.3001.5482 &#x1f355; Collection與…

【趙渝強老師】TiDB SQL層的工作機制

TiDB節點的SQL層&#xff0c;即TiDB Server&#xff0c;它負責將SQL翻譯成Key-Value操作&#xff0c;將其轉發給共用的分布式Key-Value存儲層TiKV&#xff0c;然后組裝TiKV返回的結果&#xff0c;最終將查詢結果返回給客戶端。這一層的節點都是無狀態的&#xff0c;節點本身并不…

性能遠超SAM系模型,蘇黎世大學等開發通用3D血管分割基礎模型

如果把人的身體比作一座龐大的城市&#xff0c;那么血管無疑就是這座城市的「道路」&#xff0c;動脈、靜脈以及毛細血管對應著高速公路、城市道路以及鄉間小道&#xff0c;它們相互協作&#xff0c;通過血液將營養物質、氧氣等輸送到身體各處&#xff0c;從而維持著這座「城市…

git高效殺器——cz-customizable 搭配 commitlint

What is cz-customizable and commitlint? cz-customizable 一款可定制化的Commitizen插件(也可作為獨立工具),旨在幫助創建如約定式提交規范的一致性提交消息。commitlint commitlint 是一個用于檢查 Git 提交信息的工具,它可以幫助開發者保持提交信息的規范性和一致性。…