自学内容网 自学内容网

【Vue】Vue3.0(十一)Vue 3.0 中 computed 计算属性概念、使用及示例

上篇文章:【Vue】Vue3.0(十)toRefs()和toRef()的区别及使用示例

🏡作者主页:点击!

🤖Vue专栏:点击!

⏰️创作时间:2024年10月15日10点23分

Vue 3.0中computed计算属性概念、使用及示例

一、概念

  1. 定义
    • 在Vue 3.0中,computed计算属性是一种根据其他响应式数据(如refreactive定义的数据)计算得出新值的特殊属性。它具有缓存特性,即只有当它所依赖的数据发生变化时才会重新计算,这有助于提高性能,避免不必要的计算开销。
  2. 响应式关联
    • 计算属性会自动追踪其依赖的数据。例如,如果一个计算属性依赖于一个ref创建的响应式数据,当这个ref的数据值改变时,计算属性会感知到这种变化并相应地重新计算。这种响应式关联是Vue 3.0响应式系统的重要组成部分,使得视图能够自动更新以反映数据的变化。

二、使用

(一)在Composition API中的使用

  1. 基本使用步骤
    • 导入相关函数:首先需要从vue模块中导入computedref(如果涉及ref类型的数据)等函数。例如:
    import { ref, computed } from 'vue';
    
    • 定义响应式数据:使用refreactive定义响应式数据,这些数据将作为计算属性的依赖项。例如,使用ref定义一个简单的数字类型的响应式数据:
    const count = ref(0);
    
    • 定义计算属性:在setup函数内部,使用computed函数来定义计算属性。computed函数接受一个函数作为参数,这个函数内部可以访问响应式数据并进行计算。例如:
    const doubleCount = computed(() => {
      return count.value * 2;
    });
    
    • 返回计算属性供模板使用:最后,将计算属性与其他需要在模板中使用的数据一起返回。例如:
    return {
      count,
      doubleCount
    };
    
  2. 完整示例
    import { ref, computed, defineComponent } from 'vue';
    
    export default defineComponent({
      setup() {
        const num = ref(5);
        const square = computed(() => {
          return num.value * num.value;
        });
        return {
          num,
          square
        };
      }
    });
    
    • 在这个示例中,num是一个ref类型的响应式数据,square是一个计算属性,它根据num的值计算出其平方。当num的值发生变化时,square会自动重新计算。

(二)在Options API中的使用(Vue 3.0仍然支持Options API)

  1. 基本使用步骤
    • 在组件的computed选项中定义计算属性。计算属性可以是一个函数或者一个包含getset方法的对象(如果需要可写的计算属性)。例如:
    export default {
      data() {
        return {
          firstName: 'John',
          lastName: 'Doe'
        };
      },
      computed: {
        fullName() {
          return this.firstName + ' ' + this.lastName;
        }
      }
    };
    
    • 这里fullName是一个计算属性,它依赖于data中的firstNamelastName。当firstName或者lastName发生变化时,fullName会自动重新计算。
  2. 完整示例
    import { defineComponent } from 'vue';
    
    export default defineComponent({
      data() {
        return {
          price: 10,
          quantity: 2
        };
      },
      computed: {
        totalPrice() {
          return this.price * this.quantity;
        }
      }
    });
    
    • 在这个示例中,totalPrice是计算属性,它根据pricequantity计算出总价。当price或者quantity发生变化时,totalPrice会重新计算。

三、示例

(一)计算购物车商品总价

  1. Composition API示例
    • 假设购物车中的商品是一个数组,每个商品有price(价格)和quantity(数量)属性,我们要计算购物车中商品的总价。
    import { ref, computed, defineComponent } from 'vue';
    
    export default defineComponent({
      setup() {
        const cart = ref([
          { price: 10, quantity: 2 },
          { price: 15, quantity: 3 }
        ]);
        const totalPrice = computed(() => {
          let sum = 0;
          for (let item of cart.value) {
            sum += item.price * item.quantity;
          }
          return sum;
        });
        return {
          cart,
          totalPrice
        };
      }
    });
    
    • 在这个示例中,cart是一个ref类型的数组,代表购物车中的商品列表。totalPrice是计算属性,它遍历cart中的每个商品,计算出商品的总价。当购物车中的商品的价格或者数量发生变化时,totalPrice会重新计算。

在这个示例中可能有的人会有疑问,为什么这个循环中的单个元素没有 使用.value呢 ?原因如下:

  1. 原因分析
    • 在这段代码中,cart是一个通过ref创建的响应式数据,它包含一个数组,数组中的元素是对象(如{ price: 10, quantity: 2 })。
    • 当使用for...of循环遍历cart.value(这里cart.value是一个普通的非响应式数组)时,item是数组中的每个对象元素,这些对象元素本身不是通过ref创建的响应式数据,而是普通的JavaScript对象。
    • 对于普通的JavaScript对象的属性访问,不需要使用.value。所以在computed函数内部的循环中,item.priceitem.quantity直接访问对象的属性是正确的,不需要加.value
  1. 示例对比

    • 如果pricequantity是通过ref创建的响应式数据,例如:
    const cart = ref([
      { price: ref(10), quantity: ref(2) },
      { price: ref(15), quantity: ref(3) }
    ]);
    const totalPrice = computed(() => {
      let sum = 0;
      for (let item of cart.value) {
        sum += item.price.value * item.quantity.value;
      }
      return sum;
    });
    
    • 在这种情况下,由于pricequantityref类型,就需要使用.value来获取它们的实际值进行计算。
  2. Options API示例

    import { defineComponent } from 'vue';
    
    export default defineComponent({
      data() {
        return {
          cart: [
            { price: 10, quantity: 2 },
            { price: 15, quantity: 3 }
          ]
        };
      },
      computed: {
        totalPrice() {
          let sum = 0;
          for (let item of this.cart) {
            sum += item.price * item.quantity;
          }
          return sum;
        }
      }
    });
    

(二)根据用户输入计算表达式结果

  1. Composition API示例

    • 假设用户在输入框中输入两个数字,我们要计算这两个数字的和、差、积、商(除数不为0)。
    import { ref, computed, defineComponent } from 'vue';
    
    export default defineComponent({
      setup() {
        const num1 = ref(0);
        const num2 = ref(0);
        const sum = computed(() => {
          return num1.value + num2.value;
        });
        const difference = computed(() => {
          return num1.value - num2.value;
        });
        const product = computed(() => {
          return num1.value * num2.value;
        });
        const quotient = computed(() => {
          if (num2.value!== 0) {
            return num1.value / num2.value;
          } else {
            return '除数不能为0';
          }
        });
        return {
          num1,
          num2,
          sum,
          difference,
          product,
          quotient
        };
      }
    });
    
    • 在这个示例中,num1num2ref类型的响应式数据,代表用户输入的两个数字。sumdifferenceproductquotient是计算属性,分别计算两个数字的和、差、积、商。当num1或者num2发生变化时,相应的计算属性会重新计算。
  2. Options API示例

    import { defineComponent } from 'vue';
    
    export default defineComponent({
      data() {
        return {
          num1: 0,
          num2: 0
        };
      },
      computed: {
        sum() {
          return this.num1 + this.num2;
        },
        difference() {
          return this.num1 - this.num2;
        },
        product() {
          return this.num1 * this.num2;
        },
        quotient() {
          if (this.num2!== 0) {
            return this.num1 / this.num2;
          } else {
            return '除数不能为0';
          }
        }
      }
    });
    

(三) Vue3.0中最终的一个computed使用示例:(带效果)

<template>
    <div class="person">
       姓:<input type="text" v-model="firstName"/><br/>
       名:<input type="text" v-model="lastName"/><br/>
       <button @click="changeFullName">将全名修改为li-si</button><br/>
       全名:<span>{{fullName}}</span><br/>
    </div>
</template>

<script lang="ts" setup name="Person">

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

let firstName =ref('zhang');
let lastName =ref('san');

//这么定义的计算属性,是只可读取的,不可修改的;
// let fullName = computed(()=>{
//     return firstName.value.slice(0,1).toUpperCase()
//      +firstName.value.slice(1)+'-'+lastName.value;
// })


//这么定义的fullName是一个计算属性,可读可写
let fullName =computed({
    //getter方法
    get(){
        return firstName.value.slice(0,1).toUpperCase()
              +firstName.value.slice(1)+'-'+lastName.value;
    },
    //setter方法
    set(val){
        //在setter中进行实际的修改
        const [str1,str2] =val.split('-');
        firstName.value=str1;
        lastName.value =str2;
        console.log('set', val);
        
    }
})

//修改全名 ,其实是什么也没修改这个方法里面,没有实现fullName的变化,只是引起了set的变化
function changeFullName(){
    fullName.value='li-si';
}
</script>

<style>
.person {
    background-color: skyblue;
    box-shadow: 0 0 10px;
    border-radius: 10px;
    padding: 20px;
}

li {
    font: 1em sans-serif;
}
</style>

未点击修改之前:
在这里插入图片描述
在这里插入图片描述
点击修改之后:
在这里插入图片描述


原文地址:https://blog.csdn.net/qq_39666711/article/details/142938285

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!