@xachary 2024-01-31 17:39 采纳率: 100%
浏览 6
已结题

vue3 原理关于 cleanupDepEffect 的疑问

vue3 原理关于 cleanupDepEffect 的疑问

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>reactive</title>
    <script src="../packages/vue/dist/vue.global.js"></script>
  </head>
  <body>
    <div id="app">
      <p>arr[0].v:{{arr[0].v}}</p>
      <button @click="arr.shift()">删除第一个</button>
    </div>
    <script>
      const { createApp, reactive, computed } = Vue

      const app = createApp({
        setup() {
          const arr = reactive([{ v: 1 }, { v: 2 }])
          return { arr }
        },
      }).mount('#app')
    </script>
  </body>
</html>

上面的示例,可以使代码执行到 cleanupDepEffect 内部,但我想问什么时候会出现 effect._trackId === trackId 的情况,而非 effect._trackId !== trackId。

function cleanupDepEffect(dep: Dep, effect: ReactiveEffect) {
  const trackId = dep.get(effect)
  if (trackId !== undefined && effect._trackId !== trackId) { // ←这里
    dep.delete(effect)
    if (dep.size === 0) {
      dep.cleanup()
    }
  }
}
  • 写回答

5条回答 默认 最新

  • @xachary 2024-02-01 10:40
    关注

    从测试用例挑选可复现的逻辑,如下:

    <!doctype html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>reactive</title>
        <script src="../packages/vue/dist/vue.global.js"></script>
      </head>
      <body>
        <div id="app">
          <div></div>
        </div>
        <script>
          const { createApp, reactive, watchEffect, nextTick } = Vue
    
          const app = createApp({
            setup() {
              const numbers = reactive({ num1: 3 })
    
              watchEffect(() => {
                dummy = 0
                for (let key in numbers) {
                  dummy += numbers[key]
                }
              })
    
              nextTick(() => {
                numbers.num2 = 4
                nextTick(() => {
                  delete numbers.num1
                })
              })
              return {}
            },
          }).mount('#app')
        </script>
      </body>
    </html>
    

    执行”delete numbers.num1“后,会触发 deleteProperty->trigger->...->run->postCleanupEffect->cleanupDepEffect
    此时,_depsLength 和 effect.deps.length 不同步,满足effect.deps.length > effect._depsLength,把尾部多出来的 effect 进行 cleanupDepEffect,此时可能出现 effect._trackId === trackId。
    最后进行长度的同步 effect.deps.length = effect._depsLength,至于尾部多出来的 effect 为何保留在数组里,这是另外的一个问题了。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(4条)

报告相同问题?

问题事件

  • 系统已结题 2月9日
  • 已采纳回答 2月1日
  • 修改了问题 1月31日
  • 创建了问题 1月31日

悬赏问题

  • ¥15 phython如何实现以下功能?查找同一用户名的消费金额合并—
  • ¥15 孟德尔随机化怎样画共定位分析图
  • ¥18 模拟电路问题解答有偿速度
  • ¥15 CST仿真别人的模型结果仿真结果S参数完全不对
  • ¥15 误删注册表文件致win10无法开启
  • ¥15 请问在阿里云服务器中怎么利用数据库制作网站
  • ¥60 ESP32怎么烧录自启动程序
  • ¥50 html2canvas超出滚动条不显示
  • ¥15 java业务性能问题求解(sql,业务设计相关)
  • ¥15 52810 尾椎c三个a 写蓝牙地址