Vue中的Computed實現(xiàn)原理分析
在 Vue.js 中,computed 屬性是一種強大的特性,用于定義依賴于其他響應式數(shù)據(jù)的計算值。
computed 屬性不僅能夠簡化模板中的表達式,還能夠緩存計算結果,避免不必要的重復計算,從而提高性能。
將深入探討 Vue 中 computed 屬性的實現(xiàn)原理,包括其工作機制、依賴追蹤、緩存策略等方面。
1. Computed 屬性概述
Computed 屬性是 Vue 實例中的一個特殊屬性,它允許開發(fā)者定義一個計算值,該值依賴于其他響應式數(shù)據(jù)。
Computed 屬性具有以下特點:
- 響應式:當依賴的數(shù)據(jù)發(fā)生變化時,computed 屬性會自動重新計算。
- 緩存:computed 屬性會緩存計算結果,只有當依賴的數(shù)據(jù)發(fā)生變化時,才會重新計算。
- 惰性求值:computed 屬性在首次訪問時才會進行計算,之后會根據(jù)依賴數(shù)據(jù)的變化情況決定是否重新計算。
2. Computed 屬性的基本用法
在 Vue 實例中,可以通過 computed 選項來定義 computed 屬性。
new Vue({
data() {
return {
firstName: 'John',
lastName: 'Doe'
};
},
computed: {
fullName() {
return `${this.firstName} ${this.lastName}`;
}
}
});在上述代碼中,fullName 是一個 computed 屬性,它依賴于 firstName 和 lastName。
當 firstName 或 lastName 發(fā)生變化時,fullName 會自動重新計算。
3. Computed 屬性的實現(xiàn)原理
3.1 依賴追蹤
Vue 的 computed 屬性實現(xiàn)依賴于 Vue 的響應式系統(tǒng)。
Vue 通過 Object.defineProperty 或 Proxy 來劫持數(shù)據(jù)的變化,并在數(shù)據(jù)變化時通知依賴該數(shù)據(jù)的觀察者。
3.1.1 響應式數(shù)據(jù)劫持
Vue 在初始化數(shù)據(jù)時,會通過 Object.defineProperty 或 Proxy 對數(shù)據(jù)進行劫持,使其變?yōu)轫憫綌?shù)據(jù)。
function defineReactive(obj, key, val) {
const dep = new Dep();
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get() {
if (Dep.target) {
dep.depend();
}
return val;
},
set(newVal) {
if (newVal === val) return;
val = newVal;
dep.notify();
}
});
}在上述代碼中,defineReactive 函數(shù)通過 Object.defineProperty 劫持了對象的屬性,并在 get 和 set 方法中分別收集和通知依賴。
3.1.2 依賴收集
在 computed 屬性被訪問時,Vue 會通過 Dep.target 來收集依賴。
functionWatcher(vm, expOrFn, cb) {
this.vm = vm;
this.getter = parsePath(expOrFn);
this.cb = cb;
this.value = this.get();
}
Watcher.prototype.get = function() {
Dep.target = this;
const value = this.getter.call(this.vm, this.vm);
Dep.target = null;
return value;
};
Watcher.prototype.update = function() {
const oldValue = this.value;
this.value = this.get();
this.cb.call(this.vm, this.value, oldValue);
};在上述代碼中,Watcher 實例在 get 方法中將自身設置為 Dep.target,然后訪問 computed 屬性,從而觸發(fā)依賴數(shù)據(jù)的 get 方法,完成依賴收集。
3.2 緩存策略
Computed 屬性具有緩存機制,只有在依賴數(shù)據(jù)發(fā)生變化時,才會重新計算。
3.2.1 緩存實現(xiàn)
Vue 通過 Watcher 實例的 dirty 屬性來控制緩存。
function Watcher(vm, expOrFn, cb, options) {
this.vm = vm;
this.getter = expOrFn;
this.cb = cb;
this.dirty = this.lazy = !!options.lazy;
this.value = this.lazy ? undefined : this.get();
}
Watcher.prototype.evaluate = function() {
this.value = this.get();
this.dirty = false;
};
Watcher.prototype.get = function() {
pushTarget(this);
let value;
const vm = this.vm;
try {
value = this.getter.call(vm, vm);
} finally {
popTarget();
}
return value;
};
Watcher.prototype.update = function() {
if (this.lazy) {
this.dirty = true;
} else {
this.run();
}
};在上述代碼中,Watcher 實例的 dirty 屬性用于標記 computed 屬性是否需要重新計算。
當依賴數(shù)據(jù)發(fā)生變化時,Watcher 的 update 方法會將 dirty 設置為 true,表示需要重新計算。
3.2.2 惰性求值
Computed 屬性在首次訪問時才會進行計算,之后會根據(jù) dirty 屬性決定是否重新計算。
function createComputedGetter(key) {
return function computedGetter() {
const watcher = this._computedWatchers && this._computedWatchers[key];
if (watcher) {
if (watcher.dirty) {
watcher.evaluate();
}
if (Dep.target) {
watcher.depend();
}
return watcher.value;
}
};
}在上述代碼中,createComputedGetter 函數(shù)返回一個 computed 屬性的 getter 函數(shù)。
在訪問 computed 屬性時,如果 dirty 為 true,則會調用 watcher.evaluate 方法進行計算,并將 dirty 設置為 false,表示計算結果已緩存。
4. Computed 屬性的優(yōu)化
4.1 避免不必要的計算
在定義 computed 屬性時,應盡量避免不必要的計算。
例如,如果 computed 屬性的計算邏輯較為復雜,可以考慮將其拆分為多個簡單的 computed 屬性。
computed: {
fullName() {
return `${this.firstName} ${this.lastName}`;
},
formattedName() {
return this.fullName.toUpperCase();
}
}4.2 使用 Watcher 進行性能優(yōu)化
在某些情況下,可以使用 watch 選項來替代 computed 屬性,以實現(xiàn)更細粒度的控制和性能優(yōu)化。
watch: {
firstName: 'updateFullName',
lastName: 'updateFullName'
},
methods: {
updateFullName() {
this.fullName = `${this.firstName} ${this.lastName}`;
}
}5. 總結
Vue 的 computed 屬性通過依賴追蹤和緩存策略,實現(xiàn)了響應式計算和性能優(yōu)化。
在實現(xiàn)原理上,computed 屬性依賴于 Vue 的響應式系統(tǒng),通過 Watcher 實例進行依賴收集和緩存控制。
通過深入理解和掌握 computed 屬性的實現(xiàn)原理,開發(fā)者可以更好地利用這一特性,提高應用的性能和可維護性。
在實際開發(fā)中,應根據(jù)具體需求合理使用 computed 屬性,并結合其他優(yōu)化手段,如避免不必要的計算和使用 Watcher 進行細粒度控制,從而構建高效、穩(wěn)定的 Vue 應用。
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
解決Vue3.0刷新頁面警告[Vue Router warn]:No match 
這篇文章主要介紹了解決Vue3.0刷新頁面警告[Vue Router warn]:No match found for location with path /xxx問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-03-03
vue2文件流下載成功后文件格式錯誤、打不開及內容缺失的解決方法
使用Vue時我們前端如何處理后端返回的文件流,下面這篇文章主要給大家介紹了關于vue2文件流下載成功后文件格式錯誤、打不開及內容缺失的解決方法,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下2023-04-04
實現(xiàn)vuex與組件data之間的數(shù)據(jù)同步更新方式
今天小編就為大家分享一篇實現(xiàn)vuex與組件data之間的數(shù)據(jù)同步更新方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-11-11
vue實現(xiàn)element上傳多張圖片瀏覽刪除功能
這篇文章主要介紹了vue實現(xiàn)element上傳多張圖片瀏覽刪除功能,本文結合示例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧2023-10-10
vue webpack開發(fā)訪問后臺接口全局配置的方法
今天小編就為大家分享一篇vue webpack開發(fā)訪問后臺接口全局配置的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-09-09

