欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

vue源碼解析computed多次訪問會(huì)有死循環(huán)原理

 更新時(shí)間:2023年04月04日 15:19:54   作者:Mr_shaojun  
這篇文章主要為大家介紹了vue源碼解析computed多次訪問會(huì)有死循環(huán)原理,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

正文

在上一篇中,我們仿vue源碼自己實(shí)現(xiàn)了一個(gè)computed。

寫了如下的測試代碼。

    const { reactive, effect, ref, computed } = Vue
      const obj = reactive({
        name: '張三'
      })
      // C1
      const computedObj = computed(() => {
        console.log('computed')
        return '姓名:' + obj.name
      })
      // e1
      effect(() => {
        document.querySelector('#app').innerHTML = computedObj.value
        document.querySelector('#app').innerHTML = computedObj.value
      })
      setTimeout(() => {
        obj.name = '李四'
      }, 2000)

我們發(fā)現(xiàn)computed多次訪問的時(shí)候,會(huì)出現(xiàn)死循環(huán)。

為什么會(huì)有死循環(huán)

這個(gè)問題出在哪了呢?

我們先看一下這段代碼的執(zhí)行情況。(當(dāng)時(shí)看源碼,我也是理了好幾遍,才理出頭緒。有條件的話,還是建議clone代碼自己調(diào)試一遍)

我們直接看effect。

1.先執(zhí)行effect函數(shù),設(shè)置activeEffect為傳進(jìn)來的參數(shù),也就是掛載dom的這個(gè)函數(shù),我們把這個(gè)函數(shù)就叫e1。

//叫e1
() => {
   document.querySelector('#app').innerHTML = computedObj.value
   document.querySelector('#app').innerHTML = computedObj.value
}

2.執(zhí)行e1函數(shù)

第一次執(zhí)行computedObj.value,此時(shí)會(huì)執(zhí)行如下代碼。

先是收集依賴,將e1收集起來;

【此時(shí),key為computedObj, activeEffect為e1】

因?yàn)榇藭r(shí),_dirty是true,所以會(huì)執(zhí)行computed計(jì)算函數(shù)。

執(zhí)行effect.run,也就是下面這段邏輯,我們把這個(gè)函數(shù)叫做c1

// 叫c1
() => {
  console.log('con')
  return '姓名:' + obj.name
}

執(zhí)行obj.name 觸發(fā)reactive的get,將C1收集起來。

【此時(shí),key為obj, activeEffect被改為C1】

3 第二次執(zhí)行computedObj.value

依舊會(huì)觸發(fā)一次依賴收集。

【此時(shí),key為computedObj, activeEffect已經(jīng)被改為為C1了】

此時(shí)_dirty為false,則不會(huì)執(zhí)行計(jì)算。

effct執(zhí)行完畢,此時(shí)computedObj有兩個(gè)依賴,分別是e1和c1。obj上有一個(gè)依賴,為c1

4.在2秒后,觸發(fā)obj.name的set事件,則觸發(fā)obj上的依賴函數(shù),開始遍歷執(zhí)行。

注意,因?yàn)閏omputed中使用了scheduler,所以此時(shí)的c1。

所以會(huì)執(zhí)行如下代碼

    this.effect = new ReactiveEffect(getter, () => {
      // 判斷當(dāng)前臟的狀態(tài),如果為 false,表示需要《觸發(fā)依賴》
      if (!this._dirty) {
        // 將臟置為 true,表示
        this._dirty = true
        triggerRefValue(this)
      }
    })

5.執(zhí)行triggerRefValue(this)

triggerRefValue(this)會(huì)觸發(fā)computedObj上的依賴。

此時(shí)dirty = true, 并遍歷執(zhí)行e1,c1依賴函數(shù)。

  for (const effect of effects) {
     triggerEffect(effect)
  }

6.當(dāng)執(zhí)行e1函數(shù)時(shí),又會(huì)觸發(fā)computed.get,并將e1加入依賴。

此時(shí)【key為computedObj, activeEffect為e1】

由于此時(shí),_dirty是true,則又會(huì)執(zhí)行run,重新計(jì)算。

此時(shí)【key為, activeEffect為c1】

7.當(dāng)執(zhí)行c1時(shí),因?yàn)橹癳1函數(shù)已經(jīng)將_dirty改為false了,于是又會(huì)開始執(zhí)行triggerRefValue(this),遍歷computedObj上的依賴c1和e1。

因?yàn)榇藭r(shí)computedObj依舊是有e1和c1兩個(gè)依賴,又會(huì)重新回到第5步,造成死循環(huán)。

如何解決死循環(huán)

那找到了問題,如何解決呢?

其實(shí)方法也很簡單,在第6步的時(shí)候,我們只要確保讓c1先執(zhí)行,e1后執(zhí)行就行,

先執(zhí)行c1時(shí),因?yàn)榇藭r(shí)dirty是true,所以不會(huì)重復(fù)執(zhí)行triggerRefValue(this)。

然后再執(zhí)行e1,添加依賴。

vue源碼也是這么實(shí)現(xiàn)的,先把computed的依賴執(zhí)行完,然后再執(zhí)行其他依賴。

這也就是為什么,vue源碼中觸發(fā)依賴,有兩次遍歷。

export function triggerEffects(
  dep: Dep | ReactiveEffect[],
  debuggerEventExtraInfo?: DebuggerEventExtraInfo
) {
  // spread into array for stabilization
  const effects = isArray(dep) ? dep : [...dep]
  for (const effect of effects) {
    if (effect.computed) {
      triggerEffect(effect, debuggerEventExtraInfo)
    }
  }
  for (const effect of effects) {
    if (!effect.computed) {
      triggerEffect(effect, debuggerEventExtraInfo)
    }
  }
}

總結(jié)

不管是數(shù)據(jù)的響應(yīng)式,還是computed的實(shí)現(xiàn),亦或是vue組件的更新。

本質(zhì)都是通過effec偵聽器來實(shí)現(xiàn)的。

對于effec有幾點(diǎn)要理解清楚。

1.activeEffect是會(huì)不斷變化的,這就導(dǎo)致,同樣的代碼,可能收集到的依賴函數(shù)是不一樣的。

比如上文的computedObj對象,兩次收集得依賴就是不同的,因?yàn)榈诙螞]有計(jì)算函數(shù)的執(zhí)行。

2.設(shè)置了scheduler,再次觸發(fā)的時(shí)候,執(zhí)行函數(shù)就變成了scheduler。

比如上文收集的依賴函數(shù)c1。

到這里,effet應(yīng)該有比較深入的認(rèn)識了,下一篇再講講如何通過effec偵聽器來控制更新的時(shí)機(jī),來實(shí)現(xiàn)組件更新。

以上就是vue源碼解析computed多次訪問會(huì)有死循環(huán)原理的詳細(xì)內(nèi)容,更多關(guān)于vue computed多次訪問死循環(huán)的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評論