上篇文章:【Vue】Vue3.0(十)toRefs()和toRef()的区别及使用示例
🏡作者主页:点击!
🤖Vue专栏:点击!
⏰️创作时间:2024年10月15日10点23分
文章目录
- Vue 3.0中computed计算属性概念、使用及示例
- 一、概念
- 二、使用
- (一)在Composition API中的使用
- (二)在Options API中的使用(Vue 3.0仍然支持Options API)
- 三、示例
- (一)计算购物车商品总价
- (二)根据用户输入计算表达式结果
- (三) Vue3.0中最终的一个computed使用示例:(带效果)
Vue 3.0中computed计算属性概念、使用及示例
一、概念
- 定义
- 在Vue 3.0中,
computed
计算属性是一种根据其他响应式数据(如ref
或reactive
定义的数据)计算得出新值的特殊属性。它具有缓存特性,即只有当它所依赖的数据发生变化时才会重新计算,这有助于提高性能,避免不必要的计算开销。
- 在Vue 3.0中,
- 响应式关联
- 计算属性会自动追踪其依赖的数据。例如,如果一个计算属性依赖于一个
ref
创建的响应式数据,当这个ref
的数据值改变时,计算属性会感知到这种变化并相应地重新计算。这种响应式关联是Vue 3.0响应式系统的重要组成部分,使得视图能够自动更新以反映数据的变化。
- 计算属性会自动追踪其依赖的数据。例如,如果一个计算属性依赖于一个
二、使用
(一)在Composition API中的使用
- 基本使用步骤
- 导入相关函数:首先需要从
vue
模块中导入computed
和ref
(如果涉及ref
类型的数据)等函数。例如:
import { ref, computed } from 'vue';
- 定义响应式数据:使用
ref
或reactive
定义响应式数据,这些数据将作为计算属性的依赖项。例如,使用ref
定义一个简单的数字类型的响应式数据:
const count = ref(0);
- 定义计算属性:在
setup
函数内部,使用computed
函数来定义计算属性。computed
函数接受一个函数作为参数,这个函数内部可以访问响应式数据并进行计算。例如:
const doubleCount = computed(() => { return count.value * 2; });
- 返回计算属性供模板使用:最后,将计算属性与其他需要在模板中使用的数据一起返回。例如:
return { count, doubleCount };
- 导入相关函数:首先需要从
- 完整示例
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)
- 基本使用步骤
- 在组件的
computed
选项中定义计算属性。计算属性可以是一个函数或者一个包含get
和set
方法的对象(如果需要可写的计算属性)。例如:
export default { data() { return { firstName: 'John', lastName: 'Doe' }; }, computed: { fullName() { return this.firstName + ' ' + this.lastName; } } };
- 这里
fullName
是一个计算属性,它依赖于data
中的firstName
和lastName
。当firstName
或者lastName
发生变化时,fullName
会自动重新计算。
- 在组件的
- 完整示例
import { defineComponent } from 'vue'; export default defineComponent({ data() { return { price: 10, quantity: 2 }; }, computed: { totalPrice() { return this.price * this.quantity; } } });
- 在这个示例中,
totalPrice
是计算属性,它根据price
和quantity
计算出总价。当price
或者quantity
发生变化时,totalPrice
会重新计算。
- 在这个示例中,
三、示例
(一)计算购物车商品总价
- 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呢 ?原因如下:
- 原因分析
- 在这段代码中,
cart
是一个通过ref
创建的响应式数据,它包含一个数组,数组中的元素是对象(如{ price: 10, quantity: 2 }
)。- 当使用
for...of
循环遍历cart.value
(这里cart.value
是一个普通的非响应式数组)时,item
是数组中的每个对象元素,这些对象元素本身不是通过ref
创建的响应式数据,而是普通的JavaScript对象。- 对于普通的JavaScript对象的属性访问,不需要使用
.value
。所以在computed
函数内部的循环中,item.price
和item.quantity
直接访问对象的属性是正确的,不需要加.value
。
-
示例对比
- 如果
price
和quantity
是通过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; });
- 在这种情况下,由于
price
和quantity
是ref
类型,就需要使用.value
来获取它们的实际值进行计算。
- 如果
-
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; } } });
(二)根据用户输入计算表达式结果
-
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 }; } });
- 在这个示例中,
num1
和num2
是ref
类型的响应式数据,代表用户输入的两个数字。sum
、difference
、product
和quotient
是计算属性,分别计算两个数字的和、差、积、商。当num1
或者num2
发生变化时,相应的计算属性会重新计算。
-
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>
未点击修改之前:
点击修改之后: