前端培訓(xùn):Vue3計(jì)算屬性比普通函數(shù)好的原因

前端培訓(xùn):Vue3計(jì)算屬性比普通函數(shù)好的原因

原標(biāo)題:前端訓(xùn)練:Vue3的計(jì)算性質(zhì)優(yōu)于普通函數(shù)的原因

寫(xiě)在前面

屬性計(jì)算是Vue開(kāi)發(fā)中非常實(shí)用的API,允許用戶自定義一個(gè)計(jì)算方法,然后根據(jù)一些依賴的響應(yīng)數(shù)據(jù)計(jì)算出新的值并返回。當(dāng)依賴關(guān)系發(fā)生變化時(shí),計(jì)算出的屬性會(huì)自動(dòng)重新計(jì)算得到一個(gè)新值,使用起來(lái)很方便。我們看到計(jì)算屬性本質(zhì)上是依賴關(guān)系的計(jì)算,為什么不直接使用函數(shù)呢?Vue3中的計(jì)算屬性是如何實(shí)現(xiàn)的?

屬性計(jì)算

先舉個(gè)簡(jiǎn)單的例子。我們看到設(shè)置計(jì)算屬性addOne后,直接改變addOne.value的值會(huì)出錯(cuò)?!娟P(guān)注尚硅谷,輕松學(xué)起】只有改變?cè)瓉?lái)的value count.value,才能不出錯(cuò)誤。這是因?yàn)?

如果傳遞給computed的是一個(gè)函數(shù),那就是一個(gè)getter函數(shù),只能獲取它的值,而不能直接修改它 在getter函數(shù)中,根據(jù)響應(yīng)式對(duì)象重新計(jì)算出新值,叫做計(jì)算屬性,這個(gè)響應(yīng)式對(duì)象叫做計(jì)算屬性的依賴

const count = ref(1);

const addOne = computed(()= > count . value+1);

console . log(addone . value);//2

addone . value++;//錯(cuò)誤

count . value++;

console . log(count . value);//3

那么,應(yīng)該如何修改addOne.value值呢?也就是說(shuō),在computed中設(shè)置set函數(shù)來(lái)定制值。

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ù)計(jì)算(

getter options:computed getter | writable computed options

) {

let getter: ComputedGetter

let setter: ComputedSetter

//如果傳入函數(shù),則表示只讀計(jì)算。

if(is function(getter options)){

getter = getterOrOptions

setter = __DEV__

?() => {

console.warn('寫(xiě)操作失敗:計(jì)算值是只讀的')

}

:NOOP

} else {

//不是方法說(shuō)明,而是自定義的getter setter。

getter = getterOrOptions.get

setter = getterOrOptions.set

}

let dirty = true

let值:T

讓computed: ComputedRef

//創(chuàng)建效果。當(dāng)我們看效果的源代碼時(shí),我們知道傳入的懶惰意味著它不會(huì)被立即執(zhí)行。當(dāng)計(jì)算的上游依賴性改變時(shí),觸發(fā)器轉(zhuǎn)輪效應(yīng)將被給予優(yōu)先權(quán)。當(dāng)調(diào)度器意味著效果觸發(fā)時(shí),將調(diào)用調(diào)度器而不是直接調(diào)用效果。

const runner = effect(getter,{

懶:真的,

//將效果標(biāo)記為已計(jì)算,以便它在觸發(fā)期間獲得優(yōu)先級(jí)

computed: true,

調(diào)度程序:()=> {

//觸發(fā)更新時(shí)將dirty設(shè)置為true,不會(huì)立即更新。

if(!骯臟){

臟=真

trigger(computed,TriggerOpTypes。設(shè)置,“值”)

}

}

})

//構(gòu)造一個(gè)計(jì)算返回

計(jì)算的= {

__v_isRef: true,

//可以停止如此計(jì)算的暴露效果

效果:跑步者,

獲取值(){

// dirty為true,在進(jìn)行g(shù)et操作時(shí),執(zhí)行effect以獲取最新值。

//

如果(臟){

value = runner()

臟=假

}

// dirty為false,表示值沒(méi)有更新,直接返回。

track(computed,TrackOpTypes。獲取,'值')

返回值

},

設(shè)定值(新值:T) {

setter(新值)

}

}如任何

計(jì)算的回報(bào)

}

計(jì)算的計(jì)算屬性有兩個(gè)特征:

延時(shí)計(jì)算:只有當(dāng)我們?cè)L問(wèn)計(jì)算屬性時(shí),真正運(yùn)行computed getter函數(shù)計(jì)算 緩存:它的內(nèi)部會(huì)緩存上次的計(jì)算結(jié)果value,而只有dirty為true時(shí)才會(huì)重新計(jì)算,如果訪問(wèn)計(jì)算屬性時(shí)dirty為false,那么直接返回這個(gè)value

然后,計(jì)算屬性的好處是,只要依賴關(guān)系不變,就可以使用緩存的值,而不是atguigu每次再次渲染組件時(shí)執(zhí)行函數(shù)進(jìn)行計(jì)算。

作為嵌套計(jì)算的一個(gè)小例子,我們可以看到,對(duì)于addOne,它收集的依賴是組件副作用渲染函數(shù),而對(duì)于count,它收集的依賴是addTwo內(nèi)部的runner函數(shù)。當(dāng)我們修改計(jì)數(shù)值時(shí),我們將分發(fā)通知。首先,在addOne中運(yùn)行setter函數(shù)。此時(shí)addOne中的dirty值變?yōu)閠rue,然后觸發(fā)函數(shù)再次分發(fā)通知。然后運(yùn)行addTwo中的setter函數(shù),再將addTwo中的dirty值設(shè)置為true;當(dāng)我們?cè)俅卧L問(wèn)addTwo中的值時(shí),我們發(fā)現(xiàn)如果dirty為true,我們將執(zhí)行addTwo的計(jì)算函數(shù),然后我們將執(zhí)行addOne.value+1,然后在addOne的計(jì)算函數(shù)中執(zhí)行count.value+1。這樣,最終打印出來(lái)的值就是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計(jì)算屬性的巧妙設(shè)計(jì),無(wú)論嵌套多少層,都能正常運(yùn)行。

從“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計(jì)算屬性時(shí),count.value的值還是0,而addOne.value的值是1,會(huì)觸發(fā)并執(zhí)行效果,打印出來(lái)的結(jié)果還是1。然后在執(zhí)行add()函數(shù)時(shí),會(huì)修改count.value的值,觸發(fā)執(zhí)行效果函數(shù),因?yàn)閍ddOne也是效果的依賴,addOne的runners函數(shù)也是count.value的依賴,count.value值的修改會(huì)執(zhí)行runners函數(shù),再次執(zhí)行addOne的依賴,然后觸發(fā)效果函數(shù),所以輸出兩次3。

計(jì)算函數(shù)返回的對(duì)象實(shí)際上劫持了value屬性的getter和setter,但是為什么我們?cè)诮M件的模板中訪問(wèn)一個(gè)計(jì)算屬性變量,而沒(méi)有手動(dòng)添加。價(jià)值?

推薦閱讀:

前端培訓(xùn):Vue3語(yǔ)法糖詳解分享

Web前端培訓(xùn):Vue3面試考點(diǎn)分享

前端培訓(xùn):Vue3增加了公共方法和用途

Vue3“愛(ài)”CSS變量,結(jié)果會(huì)如何返回搜狐,多看?

負(fù)責(zé)編輯:

  • 姓名:
  • 專(zhuān)業(yè):
  • 層次:
  • 電話:
  • 微信:
  • 備注:
文章標(biāo)題:前端培訓(xùn):Vue3計(jì)算屬性比普通函數(shù)好的原因
本文地址:http://balticsea-crewing.com/show-91049.html
本文由合作方發(fā)布,不代表中職學(xué)校招生網(wǎng)立場(chǎng),轉(zhuǎn)載聯(lián)系作者并注明出處:中職學(xué)校招生網(wǎng)

熱門(mén)文檔

推薦文檔