分析代码并回答问题

代码
vue 复制代码
<template>
  <div>Counter: {{ counter }}</div>
  <div>Double Counter: {{ doubleCounter }}</div>
</template>

<script setup lang="ts">
import { ref, computed } from "vue";

const counter = ref(0);

const doubleCounter = computed(() => {
  console.log("doubleCounter computed");
  return counter.value * 2;
});

setTimeout(() => {
  counter.value = 1;
}, 1000);

// 直接引用 doubleCounter
doubleCounter;
</script>

问题

  1. 代码运行时,console.log("doubleCounter computed") 会被打印几次?为什么?

    • 如果不会打印,请说明原因。
    • 如果会打印,请描述每次打印的时机。
  2. 如果将 doubleCounter; 替换为 console.log(doubleCounter.value);,会发生什么变化?

    • 分析控制台的输出结果,并解释原因。
  3. 如果在模板中移除 {``{ doubleCounter }},会对代码的行为产生什么影响?

    • 分析 console.log("doubleCounter computed") 的打印次数和时机。
  4. 如何修改代码以确保 console.log("doubleCounter computed") 在初始渲染和 counter 更新时都被打印?


答案提示

  1. 初次运行时

    • 控制台会打印 "doubleCounter computed"并在 counter 更新时再次打印。
  2. 替换为 console.log(doubleCounter.value);

    • 访问 doubleCounter.value 会触发computed的回调函数。
    • 控制台会打印 "doubleCounter computed",并在 counter 更新时再次打印。
  3. 移除模板中的 {``{ doubleCounter }}

    • 模板不再读取 doubleCounter.value,因此 computed 的回调函数不会被触发。
    • 即使 counter 更新,也不会打印 "doubleCounter computed"
  4. 确保打印的修改方式

    • 在模板中保留 {``{ doubleCounter }},或者在脚本中显式访问 doubleCounter.value(如通过watch或其他逻辑)。

总结

console.log("doubleCounter computed") 被打印的前提是以下任意一种情况:

  • 访问 doubleCounter.value:显式读取 computed 属性的值。

  • 在模板中使用 doubleCounter:Vue 自动读取 doubleCounter.value。


通过这道题目,开发者可以深入理解 Vue 的响应式系统、computed属性的工作原理,以及依赖追踪的触发条件。