Skip to content

Vue组件的computed变量调用对比

前言

Vue 组件的计算变量(computed),它在创建组件时会收集每个计算变量的依赖元素,在依赖元素改变时重新计算该计算变量。

这篇笔记对比以下4种情况下,是否会重新计算对应的计算变量:

  • 组件中没有使用该计算变量,那么依赖元素改变时,会重新计算该计算变量吗?
  • 组件中使用了该计算变量,那么依赖元素改变时,会重新计算该计算变量吗?
  • 组件中使用了该计算变量,但通过v-if导致该元素不显示时,那么依赖元素改变时,会重新计算该计算变量吗?
  • 组件中使用了该计算变量,但通过v-show导致该元素不显示时,那么依赖元素改变时,会重新计算该计算变量吗?

预览: 点击查看网页效果

测验HTML

<html>
  <head><script src="https://unpkg.com/vue@3/dist/vue.global.js"></script></head>
  <body>
    <div id="app">{{ message }}
      <ul>
        <li><span> cat count: {{catCount}}</span><button @click="changeCat">add Cat</button></li>
        <li><span> dog count: {{dogCount}}</span><button @click="changeDog">add Dog</button></li>
      </ul>
      响应式变化:
      <ul>
        <li>V1:<span>total count: <!-- {{totalCountV1}} --></span></li>
        <li>V2:<span>total count: {{totalCountV2}}</span></li>
        <li>V3:<span v-if="dogCount % 2 === 0">total count: {{totalCountV3}}</span></li>
        <li>V4:<span v-show="dogCount % 2 === 0">total count: {{totalCountV4}}</span></li>
      </ul>
      说明:
      <ul>
        <li><span>V1: 组件中未使用计算变量totalCountV1,无论何时都不会调用</span></li>
        <li><span>V2: 组件中使用了计算变量totalCountV2,依赖改变时都会调用</span></li>
        <li><span>V3: 组件中使用了计算变量totalCountV3,但通过v-if切换显示,不显示元素时则决不会调用</span></li>
        <li><span>V4: 组件中使用了计算变量totalCountV4,但通过v-show切换显示,不显示元素时则也会调用</span></li>
      </ul>
    </div>

    <script>
      const { createApp, ref } = Vue;

      const app = createApp({
          setup() {
              const message = ref('Test Vue Computed Variable!');

              const catCount = ref(0);
              const dogCount = ref(0);
              const curTime = ref(0);

              return {
                  message,
                  catCount,
                  dogCount,
                  curTime,
              }
          },
          computed:{
              totalCountV1(){
                  console.log(`V1, ${this.curTime}: catCount=${this.catCount}, dogCount=${this.dogCount}`);
                  return this.catCount + this.dogCount;
              },
              totalCountV2(){
                  console.log(`V2, ${this.curTime}: catCount=${this.catCount}, dogCount=${this.dogCount}`);
                  return this.catCount + this.dogCount;
              },
              totalCountV3(){
                  console.log(`V3, ${this.curTime}: catCount=${this.catCount}, dogCount=${this.dogCount}`);
                  return this.catCount + this.dogCount;
              },
              totalCountV4(){
                  console.log(`V4, ${this.curTime}: catCount=${this.catCount}, dogCount=${this.dogCount}`);
                  return this.catCount + this.dogCount;
              },
          },
          methods:{
              changeCat(){
                  this.curTime = new Date().getTime();
                  this.catCount += 1;
              },
              changeDog(){
                  this.curTime = new Date().getTime();
                  this.dogCount += 1;
              }
          }
      });

      app.mount('#app');
    </script>
  </body>  
</html>

console.log()结果

// 组件创建后,第一次渲染
// dogCount为偶数,都被执行一遍
V2, 0: catCount=0, dogCount=0 
V3, 0: catCount=0, dogCount=0 
V4, 0: catCount=0, dogCount=0 

// catCount改变,dogCount依旧为偶数,都被执行一遍
V2, 1709215311821: catCount=1, dogCount=0 
V3, 1709215311821: catCount=1, dogCount=0 
V4, 1709215311821: catCount=1, dogCount=0 

// dogCount不是偶数时,V2执行,V4不显示但依旧会执行
V2, 1709215314437: catCount=1, dogCount=1 
V4, 1709215314437: catCount=1, dogCount=1 
V2, 1709215328315: catCount=2, dogCount=1 
V4, 1709215328315: catCount=2, dogCount=1 

// dogCount重新变成偶数时,都被执行了
V2, 1709215330684: catCount=2, dogCount=2 
V3, 1709215330684: catCount=2, dogCount=2 
V4, 1709215330684: catCount=2, dogCount=2 

V2, 1709215332151: catCount=3, dogCount=2 
V3, 1709215332151: catCount=3, dogCount=2 
V4, 1709215332151: catCount=3, dogCount=2

总结与原理

  • V1:计算变量未被使用,则DOM中没有该变量,自然不会被调用
  • V2:计算变量被使用,会被DOM中挂载,依赖改变就自动被调用
  • V3:使用v-if导致不显示时,组件被销毁,DOM中没有该变量,不会被调用
  • V4:使用v-show导致不显示时,组件未被销毁,只是display改变导致看不见,DOM还有该变量,还会被调用