原標題:前端訓(xùn)練:Vue3的計算性質(zhì)優(yōu)于普通函數(shù)的原因
寫在前面
屬性計算是Vue開發(fā)中非常實用的API,允許用戶自定義一個計算方法,然后根據(jù)一些依賴的響應(yīng)數(shù)據(jù)計算出新的值并返回。當(dāng)依賴關(guān)系發(fā)生變化時,計算出的屬性會自動重新計算得到一個新值,使用起來很方便。我們看到計算屬性本質(zhì)上是依賴關(guān)系的計算,為什么不直接使用函數(shù)呢?Vue3中的計算屬性是如何實現(xiàn)的?
屬性計算
先舉個簡單的例子。我們看到設(shè)置計算屬性addOne后,直接改變addOne.value的值會出錯?!娟P(guān)注尚硅谷,輕松學(xué)起】只有改變原來的value count.value,才能不出錯誤。這是因為:
如果傳遞給computed的是一個函數(shù),那就是一個getter函數(shù),只能獲取它的值,而不能直接修改它 在getter函數(shù)中,根據(jù)響應(yīng)式對象重新計算出新值,叫做計算屬性,這個響應(yīng)式對象叫做計算屬性的依賴const count = ref(1);
const addOne = computed(()= > count . value+1);
console . log(addone . value);//2
addone . value++;//錯誤
count . value++;
console . log(count . value);//3
那么,應(yīng)該如何修改addOne.value值呢?也就是說,在computed中設(shè)置set函數(shù)來定制值。
const count = ref(1);
const addOne = computed({
get:()=>count.value+1,
set:val=>count.value=val-1
});
addone . value = 1;
console . log(count . value);//0
我們研究源代碼:
導(dǎo)出函數(shù)計算(
getter options:computed getter | writable computed options
) {
let getter: ComputedGetter
let setter: ComputedSetter
//如果傳入函數(shù),則表示只讀計算。
if(is function(getter options)){
getter = getterOrOptions
setter = __DEV__
?() => {
console.warn('寫操作失敗:計算值是只讀的')
}
:NOOP
} else {
//不是方法說明,而是自定義的getter setter。
getter = getterOrOptions.get
setter = getterOrOptions.set
}
let dirty = true
let值:T
讓computed: ComputedRef
//創(chuàng)建效果。當(dāng)我們看效果的源代碼時,我們知道傳入的懶惰意味著它不會被立即執(zhí)行。當(dāng)計算的上游依賴性改變時,觸發(fā)器轉(zhuǎn)輪效應(yīng)將被給予優(yōu)先權(quán)。當(dāng)調(diào)度器意味著效果觸發(fā)時,將調(diào)用調(diào)度器而不是直接調(diào)用效果。
const runner = effect(getter,{
懶:真的,
//將效果標記為已計算,以便它在觸發(fā)期間獲得優(yōu)先級
computed: true,
調(diào)度程序:()=> {
//觸發(fā)更新時將dirty設(shè)置為true,不會立即更新。
if(!骯臟){
臟=真
trigger(computed,TriggerOpTypes。設(shè)置,“值”)
}
}
})
//構(gòu)造一個計算返回
計算的= {
__v_isRef: true,
//可以停止如此計算的暴露效果
效果:跑步者,
獲取值(){
// dirty為true,在進行g(shù)et操作時,執(zhí)行effect以獲取剛剛值。
//
如果(臟){
value = runner()
臟=假
}
// dirty為false,表示值沒有更新,直接返回。
track(computed,TrackOpTypes。獲取,'值')
返回值
},
設(shè)定值(新值:T) {
setter(新值)
}
}如任何
計算的回報
}
計算的計算屬性有兩個特征:
延時計算:只有當(dāng)我們訪問計算屬性時,真正運行computed getter函數(shù)計算 緩存:它的內(nèi)部會緩存上次的計算結(jié)果value,而只有dirty為true時才會重新計算,如果訪問計算屬性時dirty為false,那么直接返回這個value然后,計算屬性的好處是,只要依賴關(guān)系不變,就可以使用緩存的值,而不是atguigu每次再次渲染組件時執(zhí)行函數(shù)進行計算。
作為嵌套計算的一個小例子,我們可以看到,對于addOne,它收集的依賴是組件副作用渲染函數(shù),而對于count,它收集的依賴是addTwo內(nèi)部的runner函數(shù)。當(dāng)我們修改計數(shù)值時,我們將分發(fā)通知。首先,在addOne中運行setter函數(shù)。此時addOne中的dirty值變?yōu)閠rue,然后觸發(fā)函數(shù)再次分發(fā)通知。然后運行addTwo中的setter函數(shù),再將addTwo中的dirty值設(shè)置為true;當(dāng)我們再次訪問addTwo中的值時,我們發(fā)現(xiàn)如果dirty為true,我們將執(zhí)行addTwo的計算函數(shù),然后我們將執(zhí)行addOne.value+1,然后在addOne的計算函數(shù)中執(zhí)行count.value+1。這樣,最終打印出來的值就是2。
const count = ref(0);
const addOne = computed(()=>{
返回count . value+1;//1
})
const addTwo = computed(()=>{
返回addone . value+1;//2
})
console . log(add two . value);//2
得益于computed計算屬性的巧妙設(shè)計,無論嵌套多少層,都能正常運行。
從“vue”導(dǎo)入{ref,computed };
從“@vue/reactivity”導(dǎo)入{ effect };
const count = ref(0);
const addOne = computed(()=>{
返回count . value+1;
})
effect(()= > console . log(addone . value+count . value))
函數(shù)add(){
count . value++;
}
add();
我們看到上面代碼的最終輸出是:1 3 3。
我們比較好次執(zhí)行addOne的computed計算屬性時,count.value的值還是0,而addOne.value的值是1,會觸發(fā)并執(zhí)行效果,打印出來的結(jié)果還是1。然后在執(zhí)行add()函數(shù)時,會修改count.value的值,觸發(fā)執(zhí)行效果函數(shù),因為addOne也是效果的依賴,addOne的runners函數(shù)也是count.value的依賴,count.value值的修改會執(zhí)行runners函數(shù),再次執(zhí)行addOne的依賴,然后觸發(fā)效果函數(shù),所以輸出兩次3。
計算函數(shù)返回的對象實際上劫持了value屬性的getter和setter,但是為什么我們在組件的模板中訪問一個計算屬性變量,而沒有手動添加。價值?
推薦閱讀:
前端培訓(xùn):Vue3語法糖詳解分享
Web前端培訓(xùn):Vue3面試考點分享
前端培訓(xùn):Vue3增加了公共方法和用途
Vue3“愛”CSS變量,結(jié)果會如何返回搜狐,多看?
負責(zé)編輯:
文章標題:前端培訓(xùn):Vue3計算屬性比普通函數(shù)好的原因
本文地址:http://balticsea-crewing.com/show-91049.html
本文由合作方發(fā)布,不代表中職學(xué)校招生網(wǎng)_55px.com.cn立場,轉(zhuǎn)載聯(lián)系作者并注明出處:中職學(xué)校招生網(wǎng)_55px.com.cn
免責(zé)聲明:本文僅代表文章作者的個人觀點,與本站無關(guān)。其原創(chuàng)性、真實性以及文中陳述文字和內(nèi)容未經(jīng)本站證實,請讀者僅作參考,并自行核實相關(guān)內(nèi)容。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請聯(lián)系郵箱:dashenkeji8@163.com,我們將在第 一 時 間進行核實處理。軟文/友鏈/推廣/廣告合作也可以聯(lián)系我。