首页
Preview

Vue3中计算属性(Computed)和响应式引用(Ref)的区别

有时候在vue3开发中,有些情况我们不知道是使用Computed还是使用Ref比较好,虽然两者都能实现功能。本文我们来探讨一下两者的差异。

计算属性(Computed)是一种基于响应式依赖关系进行缓存运算的属性。当它的依赖关系发生改变时,它就会重新求值。并且只有在它的相关依赖项发生改变时才会重新计算,否则,它会立即返回之前的计算结果,这有利于提高性能。

响应式引用(Ref)是Vue 3的新特性。它可以让我们在任何地方使用响应式数据,包括不是响应式对象的地方。Ref创建的变量被包装在一个响应式对象中,当值改变时,视图会自动更新。

比如下面的例子,可以实现一个显示帖子和点赞数量的组件:

//子组件
<template>
  <div class="post-container">
    <div class="post-footer">
      <span class="post-likes">Likes:</span>
      {{ likesRef }} <!-- 或者 likesComputed? -->
      <button class="post-like-button">👍</button>
    </div>
  </div>
</template>

<script setup>
import { ref, toRefs, watch, computed } from 'vue'
//假设有个post对象
const props = defineProps({
  post: {
    required: true,
    type: Object,
  }
})
// 可以使用ref,创建一个新的响应式引用likesRef,它的值为post.likes。
const likesRef = ref(props.post.likes)

// 也可以使用computed, 创建一个计算属性likesComputed,它的值是基于post.likes的值动态计算出来的。
//这里,计算属性的计算函数是一个返回post.likes值的箭头函数。
const likesComputed = computed(() => props.post.likes)
</script>

使用子组件:

<script setup lang="ts">
import Flow from "@/components/Flow.vue";
import {ref} from "vue";
const post = ref({likes: 123,content:'哈哈哈哈'})
</script>
<template>
  <Flow :post="post"></Flow>
</template>

这两种方式都是可以正确的显示点赞数量的。

那假设你想在一个获得1000个赞的帖子上显示一个星形"⭐️"。

你会用哪一种方式来实现呢?

  • 使用ref实现
//子组件
<template>
  <div class="post-container">
    <div class="post-footer">
      <span class="post-likes">Likes:</span>
      {{ likes }}
      <button class="post-like-button">👍</button>
      <!-- 点赞超过1000就显示⭐️ -->
      <span v-if="thousandLikes" class="post-star-icon">⭐️</span>
    </div>
  </div>
</template>
<script setup>
import { ref, toRefs, watch, computed,watchEffect } from 'vue'
const props = defineProps({
  post: {
    required: true,
    type: Object,
  }
})
const likes = ref(props.post.likes)
const thousandLikes = ref(false)
watchEffect(() => {
  if (likes.value >= 1000) {
    thousandLikes.value = true
  }
})

</script>

在这里,watchEffect 用于监视 likes 引用的值。当 likes 的值发生变化时(例如,从用户的交互中增加或者减少 likes),它就会立即触发内部的函数运行。

  • 使用computed实现 使用computed只需要写一行代码:
const likes = ref(props.post.likes)
const thousandLikes = computed(() => {
 return  likes.value >= 1000
})

使用ref或者computed,都可以显示出⭐️。

image.png

现在我们加一个按钮来控制⭐️的隐藏。

//省略
<span v-if="thousandLikes" class="post-star-icon">⭐️</span>
<button
  @click="thousandLikes = false"
  class="post-hide-star"
>
隐藏星星
</button>
//省略

使用ref是可以实现隐藏⭐️的,因为thousandLikes(ref)是一个响应式属性,可以在任何地方更新其值。

但是,如果你尝试更新 thousandLikes(computed),Vue要么会抛出一个警告,要么你的组件会崩溃。这是因为computed属性是只读的。你可以更新它的依赖项,但不能直接更新最后的结果。

如果你想使用computed,你需要在组件中添加另一个属性:

<template>
  <div class="post-container">
    <div class="post-footer">
      <span class="post-likes">Likes:</span>
      {{ likes }}
      <button class="post-like-button">👍</button>
      <!-- 点赞超过1000就显示⭐️ -->
      <span v-if="thousandLikes" class="post-star-icon">⭐️</span>
      <button
          @click="hideStar = true"
          class="post-hide-star"
      >
        隐藏星星
      </button>
    </div>
  </div>
</template>
<script setup>
//省略
const hideStar = ref(false)
const thousandLikes = computed(
  () => {
      return likes.value >= 1000 && !hideStar.value
  }
)
</script>

总结

  • ref属性是可变的响应式属性,并且只能通过向其传递对象来设置,而不能进行操作。
  • computed属性是对响应式属性进行的操作,而computed属性本身是只读的;

在实际使用中,如何选择使用计算属性还是响应式引用,取决于你的具体需求。计算属性更适合需要基于其他属性计算得出的场景,而响应式引用更适合需要跟踪其变化并在更改时触发更新的变量。

版权声明:本文内容由TeHub注册用户自发贡献,版权归原作者所有,TeHub社区不拥有其著作权,亦不承担相应法律责任。 如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

点赞(0)
收藏(0)
Hedy
大家好!我是一位前端开发工程师,拥有6年以上的前端开发经验。我熟练掌握HTML、CSS、JavaScript等语言,能够灵活运用各种前端框架,如Vue、React、Uniapp、Flutter等。我注重理论与实践相结合,能够为学员提供丰富的案例和实践项目,并以生动、易懂的语言为学员讲解前端开发的核心知识和技能。我不仅注重传授技能,更关注学员的职业发展,希望通过我的教学,帮助学员成为一名优秀的前端开发工程师。

评论(0)

添加评论