Vue 3 的響應式設計是其核心特性之一,依賴于 Proxy 和 依賴收集機制,相比 Vue 2 的 Object.defineProperty
,Vue 3 的響應式系統更加高效、靈活且易于維護。
以下是 Vue 3 響應式設計的核心原理:
一、核心機制概覽
-
使用 Proxy 實現響應式
-
Vue 3 用
Proxy
包裝對象,實現對屬性的讀取和設置的攔截(get
和set
)。 -
相比 Vue 2,
Proxy
可以監聽新增屬性和刪除屬性,避免 Vue 2 的Vue.set
限制。
-
-
依賴收集(Dep)與觸發更新(Trigger)
-
Vue 會在
getter
中收集當前運行的副作用函數(例如組件的渲染函數)。 -
當數據發生變化時,
setter
會觸發這些副作用函數,重新執行。
-
-
響應式核心工具函數
-
reactive()
:將對象轉換為響應式對象。 -
ref()
:將基本類型(如number
、string
)或對象封裝成響應式引用。 -
computed()
:計算屬性,具備緩存能力。 -
effect()
(Vue 內部 API):注冊副作用函數,用于響應式依賴追蹤。
-
二、基本流程圖
-
調用
reactive(obj)
-> 返回 Proxy 包裝對象 -
首次訪問屬性
proxy.a
-> 執行get
,收集依賴 -
修改屬性
proxy.a = 2
-> 執行set
,觸發依賴更新
三、依賴追蹤與觸發的簡化示意
// 模擬一個簡單響應式系統
let targetMap = new WeakMap();function track(target, key) {const effect = activeEffect;if (!effect) return;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(effect);
}function trigger(target, key) {const depsMap = targetMap.get(target);if (!depsMap) return;const deps = depsMap.get(key);deps && deps.forEach(effect => effect());
}let activeEffect = null;
function effect(fn) {activeEffect = fn;fn(); // 執行函數,會觸發 get,從而 trackactiveEffect = null;
}function reactive(obj) {return new Proxy(obj, {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);return result;}});
}
四、Vue 3 中響應式的優勢
特性 | Vue 2 | Vue 3 |
---|---|---|
基礎實現 | Object.defineProperty | Proxy |
新增/刪除屬性 | 需要手動使用 Vue.set | 原生支持 |
性能 | 多層嵌套對象遞歸劫持,性能差 | 延遲代理,性能好 |
API 風格 | Options API 為主 | 支持 Composition API |
五、實戰示例
import { reactive, effect } from 'vue'const state = reactive({ count: 0 })effect(() => {console.log(`count is: ${state.count}`) // 自動收集依賴
})state.count++ // 自動觸發更新
如果你需要可視化原理圖,我可以為你畫一個響應式原理的流程圖,要我幫你畫一個嗎?