计算属性
computed
当我们需要对原数据(data)进行一些额外的操纵,希望在原数据的基础之上得到一些新数据,但同时又不希望改变原数据,这种情况下,我们会选择用计算属性。
计算属性的缓存
首先,先用一段代码演示:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>计算属性</title>
</head>
<body>
<div id="app">
<p>{{cnum}}</p>
<p>{{mnum()}}</p>
<p>{{cnum}}</p>
<p>{{mnum()}}</p>
<p>{{cnum}}</p>
<p>{{mnum()}}</p>
</div>
</body>
<script src="js/vue.min.js"></script>
<script>
new Vue({
el:'#app',
data(){
return {
x:10,
y:20
}
},
// 计算属性
computed: {
cnum(){
console.log('computed');
return this.x+this.y*this.x-this.y;
}
},
methods:{
mnum(){
console.log('methods');
return this.x+this.y*this.x-this.y;
}
}
})
</script>
</html>
运行结果:
从以上结果可以看出,计算属性的结果在第一次计算完成后会缓存下来,在后续的使用,只要原数据没有发生变化,计算属性就不会再重新计算。每一次的使用都是读取缓存中的结果。
一旦计算属性中依赖的原数据发生变化,计算属性就会重新计算,也就是说,计算属性所对应的方法会重新调用。
改写Vue案例中的购物车代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>购物车</title>
<style>
table {
border-collapse: collapse;
}
th,
td {
width: 100px;
height: 50px;
text-align: center;
}
</style>
</head>
<body>
<div id="app">
<table>
<thead>
<tr>
<th>商品编号</th>
<th>商品名称</th>
<th>商品单价</th>
<th>商品数量</th>
<th>商品总价</th>
<th>商品操作</th>
</tr>
</thead>
<tbody>
<tr v-if="goodsData.every(item => item.count===0)">
<td>购物车为空</td>
</tr>
<template v-for="(item,index) in filterGoodsData">
<tr :key="item.id">
<td>{{item.id}}</td>
<td>{{item.name}}</td>
<td>{{item.price}}</td>
<td>
<button @click="item.count--">-</button>
<span>{{item.count}}</span>
<button @click="item.count++">+</button>
</td>
<td>{{item.count*item.price}}</td>
<td>
<button @click="goodsData.splice(index,1)">删除</button>
</td>
</tr>
</template>
</tbody>
</table>
<p>合计:{{totalPrice}}</p>
</div>
</body>
<script src="js/vue.min.js"></script>
<script>
new Vue({
el: '#app',
data() {
return {
goodsData: [
{ id: 1, name: '苹果', price: 20, count: 1 },
{ id: 2, name: '香蕉', price: 10, count: 2 },
{ id: 3, name: '橘子', price: 15, count: 4 }
]
}
},
computed:{
totalPrice(){
return this.goodsData.reduce((sum,item)=>{
return sum+item.price*item.count;
},0)
},
filterGoodsData(){
return this.goodsData.filter(item=>item.count>0);
}
}
})
</script>
</html>
将数量不为0的商品放到新数组中,原数组不变。
计算属性的 getter 和 setter
实例:点击按钮改变值
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>计算属性</title>
</head>
<body>
<div id="app">
<p>{{cnum}}</p>
<button @click="cnum = 'Li Si'">修改</button>
</div>
</body>
<script src="js/vue.min.js"></script>
<script>
new Vue({
el: '#app',
data() {
return {
xing:'Zhang',
ming:'Ling'
}
},
// 计算属性
computed: {
cnum: {
get() {
return this.xing +' '+ this.ming;
},
set(val) {
this.xing = val.split(' ')[0];
this.ming = val.split(' ')[1];
}
}
},
})
</script>
</html>
点击前: 点击后: