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

概述

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

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

vue3中如何创建计算属性

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

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

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

value如下几种用法

ini 复制代码
<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区别。它可实现页面和数据双向绑定

xml 复制代码
<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得到

css 复制代码
 <h2>总价1:{{ fish[0].price+fish[1].price}}</h2>
 <h2>总价2:{{ totalPrice }}</h2>

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

css 复制代码
  <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%
xml 复制代码
<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的值时

ini 复制代码
  totalPrice.value = 100;

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

修改计算属性的值

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

xml 复制代码
<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函数的内容即可:

ini 复制代码
 set(val) {
    console.log(val)
    console.log(totalPrice.value)
    fish[0].price = 40;
    fish[1].price = 60;
  }
相关推荐
敲敲敲敲暴你脑袋2 小时前
穷鬼快乐AI工具Ollama
javascript·人工智能·ollama
WayneX2 小时前
Vue 3 + TypeScript + Vite 组件库搭建,自助式生成相应组件文档
前端·javascript·vue.js
贾铭2 小时前
如何实现一个网页版的剪映(四)使用插件化思维创建pixi绘制画布(转场/滤镜)
前端·javascript
kgduu2 小时前
js之xml处理
xml·前端·javascript
凌览2 小时前
尤雨溪新公司官宣!Vite+ 正式开源,前端圈要变天了?
前端·javascript·后端
Highcharts.js2 小时前
在 Highcharts 中实现 Marimekko可变宽度图|示例教程
javascript·highcharts·图表开发·可视化图表库·可变宽图
吃西瓜的年年3 小时前
前端面试题(vue)
前端·javascript·vue.js
wuhen_n3 小时前
结构化Prompt——让AI说“人话”
前端·vue.js·ai编程
En^_^Joy4 小时前
JavaScript入门指南:从零到精通
开发语言·javascript