https://editor.csdn.net/md/?articleId=159120195

0 阅读3分钟

概述

计算属性,顾名思义,根据属性计算出一个新值,该值被称为计算属性。

  • 如根据商品数量,计算数量总和
  • 再如根据商品数量和单价计算总价

vue3中如何创建计算属性

  • 创建fish组件
  • 引入computed
  • 组件数据为鱼类和鱼类价格(鱼类单价为用户输入)
  • 计算所有鱼类总价

首先看input标签,input标签有两个属性,一是value,一是v-model,两者区别。

  • value是单向数据,只能由数据到页面
  • v-model是双向数据,即可数据到页面;也可页面输入,数据跟着响应变化

value如下几种用法

<input value="鲫鱼"/>
<input :value="fish[1].name">
<input v-bind:value="fish[1].name">

value将数据写死。:value是 v-bind:value简写方式,实现数据到页面。

v-model双向数据绑定

v-model数v-model.value缩写。注意是点,不是冒号,与v-bind:value区别。它可实现页面和数据双向绑定

<template>
  <h2>详解input:
    <input value="鲤鱼">
    <input v-bind:value="fish[0].name">
    <input :value="fish[0].name">
  </h2>
  <h2>鱼类:{{ fish[0].name }} <br>价格:<input v-model.value.number="fish[0].price"/></h2>
  <h2>鱼类:{{ fish[1].name }} <br>价格:<input v-model.number="fish[1].price"/></h2>
  <h2>总价1:{{ fish[0].price+fish[1].price}}</h2>
  <h2>总价2:{{ totalPrice }}</h2>
</template>
<script setup>
import { reactive,computed } from 'vue'
let fish = reactive([
  { name: '鲫鱼', price: 10},
  { name: '鲤鱼', price: 30 }
]);
let totalPrice= computed(() => {
  return fish[0].price + fish[1].price;
})
</script>

运行查看效果 在这里插入图片描述 价格通过两种方式计算,一是在模版中计算,二是通过计算属性totalPrice得到

 <h2>总价1:{{ fish[0].price+fish[1].price}}</h2>
 <h2>总价2:{{ totalPrice }}</h2>

为何在模版中可以计算,还要引入computed计算属性。假如数据一千条鱼,总价超过1000优惠5%,模版中应该是:

  <h2>总价2:{{
   fish.reduce((a, item) => a + item.price, 0)<1000?fish.reduce((a, item) => a + item.price, 0):(fish.reduce((a, item) => a + item.price, 0))*0.95 
  }}</h2>

此时在模版中编写业务逻辑,就变得复杂臃肿。违背一个原则,官方文档说明,尽量在模版中使用简单的表达式。

计算属性computed的特点

  • 计算属性依赖的数据变化,它才会重新计算
  • 多次引用计算属性,它只计算一次,相比与方法是要多次计算的 代码如下,创建一个方法用于计算鱼类总价,在价格超过1000时优惠5%
<template>
  <h2>鱼类:{{ fish[0].name }} <br>价格:<input v-model.value.number="fish[0].price"/></h2>
  <h2>鱼类:{{ fish[1].name }} <br>价格:<input v-model.number="fish[1].price"/></h2>
  <h2>总价1:{{ totalPrice }}</h2>
  <h2>总价2:{{ totalPrice }}</h2>
  <h2>总价3:{{ calcTotalPrice() }}</h2>
  <h2>总价4:{{ calcTotalPrice() }}</h2>
</template>
<script setup>
import { reactive,computed } from 'vue'
let fish = reactive([
  { name: '鲫鱼', price: 10},
  { name: '鲤鱼', price: 30 }
]);
function calcTotalPrice() {
  console.log('calcTotalPrice');
  const t = fish.reduce((a, item) => a + item.price, 0);
  return t< 1000 ? t : t * 0.95;
}
let totalPrice = computed(() => {
  console.log('computed');
  const t = fish.reduce((a, item) => a + item.price, 0);
  return t< 1000 ? t : t * 0.95;
})
</script>

在这里插入图片描述 事例中,计算属性和方法各引用两次。页面打开时,控制台输出一次computed,两次calcTotalPrice。每改变一次单价,computed计算一次,方法计算两次。

  • 数据变化,computed只调用一次
  • 数据变化,方法多次调用

计算属性能不能修改

通过上诉定义的计算属性totalPrice不可修改,当你通过如下代码修改totalPrice的值时

  totalPrice.value = 100;

它会提示一条警告:16 [Vue warn] Write operation failed: computed value is readonly 通过控制台打印,看看计算属性到底是什么,如图: 在这里插入图片描述计算属性使用ComputedRefImpl 结构定义,赋值时用 totalPrice.value = 100;。

修改计算属性的值

计算属性的值是可以修改的,但需要通过特殊的方法定义

<template>
  <h2>鱼类:{{ fish[0].name }} <br>价格:<input v-model.value.number="fish[0].price"/></h2>
  <h2>鱼类:{{ fish[1].name }} <br>价格:<input v-model.number="fish[1].price"/></h2>
  <h2>总价1:{{ totalPrice }}</h2>
  <button @click="calcTotalPrice">修改计算属性的值</button>

</template>
<script setup>
import { reactive,computed } from 'vue'
let fish = reactive([
  { name: '鲫鱼', price: 10},
  { name: '鲤鱼', price: 30 }
]);
function calcTotalPrice() {
  totalPrice.value = 100;

}
let totalPrice = computed({
  get() {
  const t = fish.reduce((a, item) => a + item.price, 0);
  return t< 1000 ? t : t * 0.95;
  },
  set(val) {
    console.log(val)
    console.log(totalPrice.value)

  }
})
</script>

在这里插入图片描述 如图当我们点击修改计算属性的值时,它只是调用set函数,totalPrice的值并又有改变。 原因在于,totalPrice是根据鱼的价格计算而来,只有改变鱼的价格,才能够改变totalPrice值。修改set函数的内容即可:

 set(val) {
    console.log(val)
    console.log(totalPrice.value)
    fish[0].price = 40;
    fish[1].price = 60;
  }