computed计算属性
顾名思义,首先它是一种属性,其次它有“计算”这个特殊性质。每次取得它的值的时候,它并不像普通属性那样直接返回结果,而是经过一系列的计算之后再返回结果。 同时只要在它的当中里引用了 data 中的某个属性,当这个属性发生变化时,计算属性仿佛可以嗅探到这个变化,并自动重新执行。
计算属性和方法的区别:
- 计算属性是基于它们的依赖进行缓存的。计算属性只有在它的相关依赖发生改变时才会重新求值。
- 方法绑定数据只要被调用,方法将总会再次执行函数。
- 计算属性相对于方法在处理特定场合下节省资源性能
计算属性和侦听器的区别:
- 当watch监听的值发生改变就会被调用,watch可以在数据变化时做一些异步处理或者开销大的操作
- 计算属性是计算依赖的值,当依赖的值发生改变才会触发。
<template>
<input type="text" v-model="fistName">
<input type="text" v-model="lastName">
<p>{{ fullName }}</p>
<button @click="change">change</button>
</template>
<script setup lang="ts">
import {computed, ref} from "vue";
let fistName = ref('Lv')
let lastName = ref('Yang')
// 普通写法
// const fullName = computed(() => {
// return fistName.value + lastName.value
// })
// 完整写法
let fullName = computed({
get() {
return fistName.value + lastName.value
},
set(newValue) {
console.log(newValue)
const nameArr = newValue.split(',')
fistName.value = nameArr[0]
lastName.value = nameArr[1]
},
})
const change = () => {
fullName.value = 'Xv,YiNuo'
}
</script>
购物车案例
<template>
<label>
名称:
<input v-model="commodityName"/>
</label>
<label>
单价:
<input type="number" v-model="price"/>
</label>
<button @click="add">添加</button>
<table border="1" cellpadding="10" cellspacing="0" width="1000px">
<thead>
<tr>
<th>名称</th>
<th>数量</th>
<th>单价</th>
<th>总价</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for="(game,index) in games" :key="index">
<td>
{{ game.name }}
</td>
<td>
<button @click="addAndSub(game,false)">-</button>
<span style="display: inline-block;width: 30px;">{{ game.num }}</span>
<button @click="addAndSub(game,true)">+</button>
</td>
<td>
{{ game.price }}
</td>
<td>
{{ game.price * game.num }}
</td>
<td>
<button @click="del(game)">删除</button>
</td>
</tr>
</tbody>
</table>
<h2>总价格:{{ fullPrice }}</h2>
</template>
<script setup lang="ts">
import {computed, reactive, Ref, ref} from "vue";
// 每个商品类型
type Shop = {
name: string,
num: number,
price: number
}
// 商品名
let commodityName: Ref<string> = ref<string>('')
// 商品价格
let price: Ref<number> = ref<number>(0)
const games = reactive<Shop[]>([
{
name: '重装机兵',
num: 0,
price: 10
},
{
name: '勇者斗恶龙',
num: 0,
price: 20
},
{
name: '生化危机',
num: 0,
price: 30
}
])
// 增加或者减少数量
const addAndSub = (game: Shop, type: boolean): void => {
if (type) {
if (game.num < 99) game.num++
} else {
if (game.num > 1) game.num--
}
}
// 添加
const add = () => {
if (commodityName.value === '' || price.value === '') return
games.push({
name: commodityName.value,
num: 0,
price: price.value
})
commodityName.value = ''
price.value = ''
}
// 删除
const del = (game: Shop): void => {
games.splice(games.findIndex((item) => game.name === item.name), 1)
}
// 总价
const fullPrice = computed(() => games.reduce((prev, currentValue) => prev + (currentValue.price * currentValue.num), 0))
</script>
<style>
td, th {
text-align: center;
}
</style>