Vue3使用Proxy構(gòu)建高效響應(yīng)式數(shù)據(jù)的示例代碼
Proxy 的核心機(jī)制
在 Vue 3 中,Proxy 主要用于 攔截對(duì)象的基本操作,包括 屬性讀?。╣et)、修改(set)、刪除(deleteProperty) 等。這是 Vue 3 取代 Object.defineProperty 的根本原因。
Proxy 允許攔截的操作:
操作 | 作用 |
---|---|
get(target, key, receiver) | 讀取屬性時(shí)觸發(fā) |
set(target, key, value, receiver) | 設(shè)置屬性時(shí)觸發(fā) |
deleteProperty(target, key) | 刪除屬性時(shí)觸發(fā) |
has(target, key) | 判斷 key 是否存在(key in obj) |
ownKeys(target) | 獲取對(duì)象的所有鍵(Object.keys(obj)) |
apply(target, thisArg, args) | 代理函數(shù)調(diào)用 |
construct(target, args) | 代理 new 操作符 |
Proxy 的核心實(shí)現(xiàn)
讓我們通過一個(gè) 手寫 Proxy 劫持 的例子,模擬 Vue 3 響應(yīng)式數(shù)據(jù)的基本實(shí)現(xiàn):
const handler = { get(target, key) { console.log(`讀取屬性:${key}`); return Reflect.get(target, key); }, set(target, key, value) { console.log(`修改屬性:${key} -> ${value}`); return Reflect.set(target, key, value); } }; const data = { message: "Hello Vue 3" }; const proxyData = new Proxy(data, handler); console.log(proxyData.message); // 讀取屬性:message proxyData.message = "Updated"; // 修改屬性:message -> Updated
解讀:
? • Reflect.get(target, key):用于獲取目標(biāo)對(duì)象的值,等價(jià)于 target[key]。
? • Reflect.set(target, key, value):用于修改目標(biāo)對(duì)象的值,等價(jià)于 target[key] = value。
? • Vue 3 就是基于 Proxy 設(shè)計(jì) reactive() 來創(chuàng)建響應(yīng)式數(shù)據(jù)。
Vue 3 如何基于 Proxy 構(gòu)建響應(yīng)式系統(tǒng)
Vue 3 的核心響應(yīng)式 API reactive() 就是對(duì) Proxy 的封裝,具體實(shí)現(xiàn)如下:
function reactive(target) { if (typeof target !== "object" || target === null) { return target; } return new Proxy(target, { get(target, key, receiver) { console.log(`訪問屬性:${key}`); return Reflect.get(target, key, receiver); }, set(target, key, value, receiver) { console.log(`修改屬性:${key} -> ${value}`); return Reflect.set(target, key, value, receiver); } }); } const state = reactive({ count: 0 }); console.log(state.count); // 訪問屬性:count state.count++; // 修改屬性:count -> 1
Vue 3 reactive() 實(shí)現(xiàn)的核心點(diǎn)
? 1. 使用 Proxy 劫持整個(gè)對(duì)象,而不是每個(gè)屬性。
? 2. 支持深層次代理(但 Vue 3 默認(rèn)是惰性代理,訪問時(shí)才創(chuàng)建嵌套對(duì)象的代理)。
? 3. 攔截?cái)?shù)組和對(duì)象的方法(如 push、pop、delete) 。
Vue 3 的依賴收集與副作用處理機(jī)制
Vue 3 采用 “響應(yīng)式依賴收集 + 依賴觸發(fā)” 來完成視圖更新,核心組件包括:
? • reactive():創(chuàng)建響應(yīng)式數(shù)據(jù)(基于 Proxy)。
? • effect():收集依賴,記錄哪些屬性被訪問。
? • trigger():數(shù)據(jù)變更時(shí)通知所有依賴執(zhí)行。
1. Vue 3 依賴收集的核心實(shí)現(xiàn)
let activeEffect = null; // 當(dāng)前正在執(zhí)行的 effect const targetMap = new WeakMap(); // 存儲(chǔ)依賴 function effect(fn) { activeEffect = fn; fn(); // 立即執(zhí)行一次,收集依賴 activeEffect = null; } function track(target, key) { if (activeEffect) { let 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) return; const effects = depsMap.get(key); if (effects) { effects.forEach(fn => fn()); // 觸發(fā)所有依賴 } } // 結(jié)合 Proxy 創(chuàng)建 Vue 3 響應(yīng)式對(duì)象 function reactive(target) { return new Proxy(target, { get(target, key, receiver) { track(target, key); // 依賴收集 return Reflect.get(target, key, receiver); }, set(target, key, value, receiver) { const result = Reflect.set(target, key, value, receiver); trigger(target, key); // 觸發(fā)更新 return result; } }); }
2. Vue 3 響應(yīng)式數(shù)據(jù)的完整示例
const state = reactive({ count: 0 }); effect(() => { console.log(`count 更新:${state.count}`); }); state.count++; // 觸發(fā)更新:count 更新:1 state.count = 5; // 觸發(fā)更新:count 更新:5
執(zhí)行流程:
? 1. effect(() => console.log(state.count)) 執(zhí)行時(shí),觸發(fā) get(),收集 state.count 的依賴。
? 2. state.count++ 觸發(fā) set(),調(diào)用 trigger() 通知所有依賴執(zhí)行 effect()。
Vue 3 Proxy 響應(yīng)式系統(tǒng)的優(yōu)化
1. 依賴按需收集
Vue 2 在初始化時(shí)遍歷整個(gè)對(duì)象,而 Vue 3 只有在 訪問屬性時(shí)才進(jìn)行代理,減少性能消耗。
2. 自動(dòng)清理無效依賴
Vue 3 采用 WeakMap + Set 進(jìn)行依賴存儲(chǔ),避免內(nèi)存泄漏,Vue 2 需要手動(dòng)管理依賴刪除。
3. 只更新受影響的組件
Vue 3 的 trigger() 機(jī)制讓每個(gè)組件只更新它所依賴的部分,避免 Vue 2 中全局重新計(jì)算的問題。
總結(jié)
Proxy 使 Vue 3 的響應(yīng)式系統(tǒng)更高效,支持新增屬性監(jiān)聽、數(shù)組操作攔截等。依賴追蹤采用 WeakMap + Set 存儲(chǔ),提高性能,避免 Vue 2 的內(nèi)存泄漏問題。 Vue 3 采用 Lazy Proxy(惰性代理),只有訪問屬性時(shí)才進(jìn)行代理,減少初始化開銷。Vue 3 的響應(yīng)式機(jī)制通過effect() 進(jìn)行自動(dòng)依賴收集,讓數(shù)據(jù)更新更智能、更高效。
以上就是Vue3使用Proxy構(gòu)建高效響應(yīng)式數(shù)據(jù)的示例代碼的詳細(xì)內(nèi)容,更多關(guān)于Vue3 Proxy響應(yīng)式數(shù)據(jù)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Vue文件下載進(jìn)度條的實(shí)現(xiàn)過程
這篇文章主要介紹了Vue文件下載進(jìn)度條的實(shí)現(xiàn)原理,通過使用onDownloadProgress方法API獲取進(jìn)度及文件大小等數(shù)據(jù),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-07-07Vue2+SpringBoot實(shí)現(xiàn)數(shù)據(jù)導(dǎo)出到csv文件并下載的使用示例
本文主要介紹了Vue2+SpringBoot實(shí)現(xiàn)數(shù)據(jù)導(dǎo)出到csv文件并下載,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-10-10vue+webpack模擬后臺(tái)數(shù)據(jù)的示例代碼
這篇文章主要介紹了vue+webpack模擬后臺(tái)數(shù)據(jù)的示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-07-07基于vue實(shí)現(xiàn)一個(gè)神奇的動(dòng)態(tài)按鈕效果
今天我們將利用vue的條件指令來完成一個(gè)簡(jiǎn)易的動(dòng)態(tài)變色功能按鈕,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2019-05-05Vue設(shè)置select下拉框的默認(rèn)選項(xiàng)詳解(select空白bug解決)
最近開始學(xué)習(xí)vue,在學(xué)習(xí)的過程中遇到的問題將記錄在這里,下面這篇文章主要給大家介紹了關(guān)于Vue設(shè)置select下拉框的默認(rèn)選項(xiàng)(select空白bug解決)的相關(guān)資料,需要的朋友可以參考下2022-12-12VUE 實(shí)現(xiàn)一個(gè)簡(jiǎn)易老虎機(jī)的項(xiàng)目實(shí)踐
老虎機(jī)在很多地方都可以見到,可以設(shè)置中獎(jiǎng)位置,以及中獎(jiǎng)回調(diào),本文主要介紹了VUE 實(shí)現(xiàn)一個(gè)簡(jiǎn)易老虎機(jī)的項(xiàng)目實(shí)踐,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-04-04對(duì)Vue table 動(dòng)態(tài)表格td可編輯的方法詳解
今天小編就為大家分享一篇對(duì)Vue table 動(dòng)態(tài)表格td可編輯的方法詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-08-08vue實(shí)現(xiàn)input框禁止輸入標(biāo)簽
這篇文章主要介紹了vue實(shí)現(xiàn)input框禁止輸入標(biāo)簽,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-04-04