Vue中的Computed實現(xiàn)原理分析
在 Vue.js 中,computed 屬性是一種強大的特性,用于定義依賴于其他響應(yīng)式數(shù)據(jù)的計算值。
computed 屬性不僅能夠簡化模板中的表達式,還能夠緩存計算結(jié)果,避免不必要的重復(fù)計算,從而提高性能。
將深入探討 Vue 中 computed 屬性的實現(xiàn)原理,包括其工作機制、依賴追蹤、緩存策略等方面。
1. Computed 屬性概述
Computed 屬性是 Vue 實例中的一個特殊屬性,它允許開發(fā)者定義一個計算值,該值依賴于其他響應(yīng)式數(shù)據(jù)。
Computed 屬性具有以下特點:
- 響應(yīng)式:當依賴的數(shù)據(jù)發(fā)生變化時,computed 屬性會自動重新計算。
- 緩存:computed 屬性會緩存計算結(jié)果,只有當依賴的數(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 的響應(yīng)式系統(tǒng)。
Vue 通過 Object.defineProperty 或 Proxy 來劫持數(shù)據(jù)的變化,并在數(shù)據(jù)變化時通知依賴該數(shù)據(jù)的觀察者。
3.1.1 響應(yīng)式數(shù)據(jù)劫持
Vue 在初始化數(shù)據(jù)時,會通過 Object.defineProperty 或 Proxy 對數(shù)據(jù)進行劫持,使其變?yōu)轫憫?yīng)式數(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 方法中將自身設(shè)置為 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 設(shè)置為 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,則會調(diào)用 watcher.evaluate 方法進行計算,并將 dirty 設(shè)置為 false,表示計算結(jié)果已緩存。
4. Computed 屬性的優(yōu)化
4.1 避免不必要的計算
在定義 computed 屬性時,應(yīng)盡量避免不必要的計算。
例如,如果 computed 屬性的計算邏輯較為復(fù)雜,可以考慮將其拆分為多個簡單的 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. 總結(jié)
Vue 的 computed 屬性通過依賴追蹤和緩存策略,實現(xiàn)了響應(yīng)式計算和性能優(yōu)化。
在實現(xiàn)原理上,computed 屬性依賴于 Vue 的響應(yīng)式系統(tǒng),通過 Watcher 實例進行依賴收集和緩存控制。
通過深入理解和掌握 computed 屬性的實現(xiàn)原理,開發(fā)者可以更好地利用這一特性,提高應(yīng)用的性能和可維護性。
在實際開發(fā)中,應(yīng)根據(jù)具體需求合理使用 computed 屬性,并結(jié)合其他優(yōu)化手段,如避免不必要的計算和使用 Watcher 進行細粒度控制,從而構(gòu)建高效、穩(wěn)定的 Vue 應(yīng)用。
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
vue實現(xiàn)excel文件導(dǎo)入導(dǎo)出操作示例
這篇文章主要為大家介紹了vue實現(xiàn)excel文件的導(dǎo)入導(dǎo)出實現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-07-07
vue el-form-item如何添加icon和tooltip
這篇文章主要介紹了vue el-form-item如何添加icon和tooltip問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-10-10
Vue.js中實現(xiàn)密碼修改及頁面跳轉(zhuǎn)和刷新的完整指南
在現(xiàn)代Web應(yīng)用中,用戶賬戶管理是一個核心功能,其中密碼修改是一個常見的需求,本文將詳細介紹如何在Vue.js應(yīng)用中實現(xiàn)用戶密碼修改功能,并在成功后跳轉(zhuǎn)到登錄頁面并刷新該頁面,需要的朋友可以參考下2024-12-12
element-ui Upload上傳組件動態(tài)配置action方式
這篇文章主要介紹了element-ui Upload上傳組件動態(tài)配置action方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-07-07
vue.js實現(xiàn)數(shù)據(jù)庫的JSON數(shù)據(jù)輸出渲染到html頁面功能示例
這篇文章主要介紹了vue.js實現(xiàn)數(shù)據(jù)庫的JSON數(shù)據(jù)輸出渲染到html頁面功能,結(jié)合實例形式分析了vue.js針對本地json數(shù)據(jù)的讀取、遍歷輸出相關(guān)操作技巧,需要的朋友可以參考下2019-08-08
Vue項目在IE瀏覽器頁面白屏且報錯SCRIPT1010:缺少標識符問題
Vue項目在谷歌瀏覽器中正常運行,但在IE瀏覽器中出現(xiàn)問題,如白屏和控制臺報錯,解決過程包括檢查IE設(shè)置、調(diào)整編輯器配置、引入兼容性插件、使用productionSourceMap定位錯誤、檢查插件依賴和版本,以及重新構(gòu)建項目2024-09-09
Vue結(jié)合原生js實現(xiàn)自定義組件自動生成示例
這篇文章主要介紹了Vue結(jié)合原生js實現(xiàn)自定義組件自動生成示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-01-01

