【Vue3 知识第八讲】computed 计算属性基础知识详解

一、 概述

模板中的表达式虽然方便,但也只能用来做简单的操作。如果在模板中写太多逻辑,会让模板变得臃肿,难以维护。因此我们推荐使用计算属性来描述依赖响应式状态的复杂逻辑。

computed 计算属性本质是 Vue 中内置的一个函数。用于当依赖的属性值发生改变的时候,触发其数据的更改。如果依赖的值不发生变化,则使用缓存中的属性值。

数字化管理平台
Vue3+Vite+VueRouter+Pinia+Axios+ElementPlus
权限系统-商城
个人博客地址

computed属性是Vue3中的一个响应式计算属性,它可以根据其他响应式数据的变化而自动更新其自身的值。computed属性可以接收一个计算函数,并在计算函数中使用其他响应式数据的值进行计算。当任何一个参与计算的响应式数据发生变化时,computed属性会自动重新计算其值,并触发相应的依赖更新。

在Vue3中,computed属性的原理是使用了一个getter函数和一个setter函数来实现。当我们访问计算属性的值时,会调用getter函数进行计算,并将计算结果缓存起来。当参与计算的响应式数据发生变化时,会触发依赖更新,并自动调用getter函数重新计算计算属性的值。当我们修改计算属性的值时,会调用setter函数进行更新。

二、接收一个回调函数作为参数

computed() 方法期望接收一个 getter 函数,返回值为一个计算属性 ref。和其他一般的 ref 类似,你可以通过 .value 访问计算结果。计算属性 ref 也会在模板中自动解包,因此在模板表达式中引用时无需添加 .value

import { computed, reactive, ref } from 'vue'

let str = ref("Hello Computed!")
 
let mstr = computed(()=>{
   // 反转字符串
   return str.value.split('').reverse().join('')
})
 
str.value = "Welcome to Beijing!"

三、接收一个对象作为参数

计算属性默认是只读的。当你尝试修改一个计算属性时,你会收到一个运行时警告。只在某些特殊场景中你可能才需要用到“可写”的属性,你可以通过同时提供 getter 和 setter 来创建:

<template>
    <div>{
   
   { str }} ~ {
   
   { mstr }}}</div>
    <div @click="change">修改依赖数据</div>
</template>
 
<script setup lang="ts">
    import { computed, ref } from "vue";
    let str = ref("Hello Vue!");
    let mstr = computed({
      get: () => {
        return str.value.split("").reverse().join("");
      },
      set: (newValue) => {
        str.value = newValue;
      },
    });

    const change = () => {
      mstr.value = "Welcome to Beijing!";
    };
</script>
  1. 这里尝试修改计算属性,当你运行 mstr.value = 'Welcome to Beijing!' 时,setter 会被调用而 str 会随之更新。
  2. 避免直接修改计算属性值。从计算属性返回的值是派生状态。可以把它看作是一个“临时快照”,每当源状态发生变化时,就会创建一个新的快照。更改快照是没有意义的,因此计算属性的返回值应该被视为只读的,并且永远不应该被更改——应该更新它所依赖的源状态以触发新的计算。

四、计算属性 VS 方法

一般情况下,在表达式中调用一个函数也会获得和计算属性相同的结果。不同之处在于计算属性值会基于其响应式依赖被缓存。一个计算属性仅会在其响应式依赖更新时才重新计算。

这意味着只要 str 不改变,无论多少次访问 mstr 都会立即返回先前的计算结果,而不用重复执行 getter 函数。相比之下,方法调用总是会在重渲染发生时再次执行函数。

为什么需要缓存呢?

想象一下我们有一个非常耗性能的计算属性 list,需要循环一个巨大的数组并做许多计算逻辑,并且可能也有其他计算属性依赖于 list。没有缓存的话,我们会重复执行非常多次 list 的 getter,然而这实际上没有必要!如果你确定不需要缓存,那么也可以使用方法调用。

五、computed函数的使用场景

computed属性通常用于处理需要根据其他响应式数据计算得出的值的情况。下面是一些computed属性的使用场景

5.1 过滤和排序

我们需要根据其他响应式数据进行数据过滤和排序时,可以使用computed属性来计算得出过滤和排序后的结果。例如:

import {
    
     computed, reactive } from 'vue'

const state = reactive({
    
    
  todos: [
    {
    
     id: 1, text: '学习Vue3', done: false },
    {
    
     id: 2, text: '学习React', done: false },
    {
    
     id: 3, text: '学习Angular', done: true }
  ],
  filter: 'all'
})

const filteredTodos = computed(() => {
    
    
  if (state.filter === 'all') {
    
    
    return state.todos
  } else if (state.filter === 'active') {
    
    
    return state.todos.filter(todo => !todo.done)
  } else if (state.filter === 'completed') {
    
    
    return state.todos.filter(todo => todo.done)
  }
})

console.log(filteredTodos.value) // 输出:[{ id: 1, text: '学习Vue3', done: false }, { id: 2, text: '学习React', done: false }, { id: 3, text: '学习Angular', done: true }]

state.filter = 'active'

console.log(filteredTodos.value) // 输出:[{ id: 1, text: '学习Vue3', done: false }, { id: 2, text: '学习React', done: false }]

在上面的例子中,我们使用computed函数定义了一个计算属性filteredTodos,它根据state.todos和state.filter的值进行过滤,并返回过滤后的结果。当state.filter的值发生变化时,filteredTodos的值也会自动更新。

5.2 数组计算

当我们需要对一个数组进行计算时,可以使用computed属性来计算得出数组的值。例如:

import {
    
     computed, reactive } from 'vue'

const state = reactive({
    
    
  todos: [
    {
    
     id: 1, text: '学习Vue3', done: false },
    {
    
     id: 2, text: '学习React', done: false },
    {
    
     id: 3, text: '学习Angular', done: true }
  ]
})

const totalTodos = computed(() => {
    
    
  return state.todos.length
})

const completedTodos = computed(() => {
    
    
  return state.todos.filter(todo => todo.done).length
})

console.log(totalTodos.value) // 输出:3
console.log(completedTodos.value) // 输出:1


在上面的例子中,我们使用computed函数定义了两个计算属性totalTodos和completedTodos,它们分别计算了state.todos数组的总长度和已完成的数量。当state.todos数组的值发生变化时,totalTodos和completedTodos的值也会自动更新。

猜你喜欢

转载自blog.csdn.net/qq_39335404/article/details/132663746
今日推荐