首页 > 编程知识 正文

Vue中computed数据变化但视图不更新的问题解决

时间:2023-11-19 20:22:35 阅读:289981 作者:VLDR

在Vue中,我们通常使用computed属性来计算一个值,这样我们可以方便地在模板中使用这个值。但是有时候,我们会遇到这样的问题:computed里面的数据打印出来变化了,但是视图里面没有变化。本文将会深入探讨这个问题。

一、什么是computed属性

Vue中computed属性是计算属性,它在Vue实例中用于计算一个值。computed的值是只读的,它们依赖于其他属性的值,并且只有在依赖的值发生改变时才会重新求值。

例如,我们可以使用computed属性计算两个数字的和:


<template>
  <div>{{ result }}</div>
</template>

<script>
export default {
  data() {
    return {
      num1: 1,
      num2: 2,
    };
  },
  computed: {
    result() {
      return this.num1 + this.num2;
    },
  },
};
</script>

在上面的例子中,result是一个只读的computed属性,它依赖于num1和num2两个属性,只有当这两个属性发生变化时,result才会重新计算。

二、computed属性的计算过程

计算computed属性的过程是一个异步的过程,Vue会在下一次事件循环中计算computed属性。这是为了避免不必要的计算,提升性能。

下面的例子演示了computed属性的计算过程:


<template>
  <div>{{ result }}</div>
  <button @click="changeNum">Change Num</button>
</template>

<script>
export default {
  data() {
    return {
      num1: 1,
      num2: 2,
    };
  },
  computed: {
    result() {
      console.log("computed");
      return this.num1 + this.num2;
    },
  },
  methods: {
    changeNum() {
      this.num1++;
    },
    changeNumSync() {
      this.num2++;
    },
  },
};
</script>

在上面的例子中,当我们点击Change Num按钮时,num1属性会加1,这会导致result属性发生变化,因此Vue会在下一次事件循环中计算result属性。我们可以在浏览器的控制台中看到"computed"这个输出。

三、computed属性不更新的原因

因为computed属性的计算过程是异步的,所以如果computed属性依赖的属性发生变化时,如果Vue在下一次事件循环之前检测到了这个变化并更新了computed属性,那么视图就会自动更新。

但是,如果computed属性依赖的属性发生变化后,Vue没有在下一次事件循环之前检测到这个变化,computed属性就不会更新,视图也就不会更新。

下面的例子演示了computed属性不更新的情况:


<template>
  <div>{{ result }}</div>
  <button @click="changeNum">Change Num</button>
</template>

<script>
export default {
  data() {
    return {
      num1: 1,
      num2: 2,
    };
  },
  computed: {
    result() {
      console.log("computed");
      return this.num1 + this.num2;
    },
  },
  methods: {
    changeNum() {
      this.num1++;
      this.$nextTick(() => {
        console.log(this.result);
      });
    },
  },
};
</script>

在上面的例子中,我们在changeNum方法中加了一个$nextTick方法,这个方法会在下一次事件循环中执行。在$nextTick方法中,我们打印了result属性的值。这个值会比实际的值晚一步。这是因为在num1的值发生变化后,Vue没有在下一次事件循环之前检测到这个变化,computed属性没有更新,result的值也就没有更新。

四、解决computed属性不更新的方法

我们可以使用以下方法解决computed属性不更新的问题:

4.1 使用watch监听属性变化

我们可以使用watch监听num1和num2属性的变化,并在变化时强制重新计算computed属性。这样,即使Vue没有在下一次事件循环之前检测到属性的变化,computed属性也会更新。


<template>
  <div>{{ result }}</div>
  <button @click="changeNum">Change Num</button>
</template>

<script>
export default {
  data() {
    return {
      num1: 1,
      num2: 2,
    };
  },
  computed: {
    result() {
      console.log("computed");
      return this.num1 + this.num2;
    },
  },
  watch: {
    num1: {
      handler() {
        this.$forceUpdate();
      },
    },
    num2: {
      handler() {
        this.$forceUpdate();
      },
    },
  },
  methods: {
    changeNum() {
      this.num1++;
    },
  },
};
</script>

在上面的例子中,我们使用watch监听了num1和num2属性的变化,并在变化时强制重新计算computed属性。这样,即使Vue没有在下一次事件循环之前检测到属性的变化,computed属性也会更新。

4.2 使用key让Vue重新渲染组件

当Vue检测到组件的key发生变化时,它会销毁当前的组件并重新创建一个新的组件,这样就能够强制computed属性重新计算。


<template>
  <div :key="num1">{{ result }}</div>
  <button @click="changeNum">Change Num</button>
</template>

<script>
export default {
  data() {
    return {
      num1: 1,
      num2: 2,
    };
  },
  computed: {
    result() {
      console.log("computed");
      return this.num1 + this.num2;
    },
  },
  methods: {
    changeNum() {
      this.num1++;
    },
  },
};
</script>

在上面的例子中,我们使用:num1作为组件的key,这样当num1变化时,Vue会重新渲染组件,computed属性也会重新计算。

4.3 手动调用$forceUpdate方法

$forceUpdate方法会强制组件重新渲染,在重新渲染时,computed属性也会重新计算。


<template>
  <div>{{ result }}</div>
  <button @click="changeNum">Change Num</button>
</template>

<script>
export default {
  data() {
    return {
      num1: 1,
      num2: 2,
    };
  },
  computed: {
    result() {
      console.log("computed");
      return this.num1 + this.num2;
    },
  },
  methods: {
    changeNum() {
      this.num1++;
      this.$forceUpdate();
    },
  },
};
</script>

在上面的例子中,当num1的值发生变化时,我们手动调用了$forceUpdate方法,这会强制组件重新渲染,在重新渲染时,computed属性也会重新计算。

五、小结

本文深入探讨了在Vue中使用computed属性时出现的computed里面的数据打印出来变化了,但是视图里面没有变化的问题。我们从computed属性的计算过程、computed属性不更新的原因和解决方法三个方面进行了详细的阐述。最终,我们提出了使用watch监听属性变化、使用key让Vue重新渲染组件和手动调用$forceUpdate方法三种解决方法。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。