vue---十分钟搞懂vue计算属性
计算属性本质上就是一个 function 函数,它可以实时监听 data 中数据的变化,并 return 一个计算后的新值,供组件渲染 DOM 时使用。✨个人笔记博客✨星月前端博客✨原创不易,还希望各位大佬支持一下✏️评论,你的意见是我进步的财富!......
·
计算属性
前言
这篇文章介绍vue组件基础中的计算属性,文章持续输出中!
废话不多说,直接上刺刀!!
1. 什么是计算属性
计算属性本质上就是一个 function 函数,它可以实时监听 data 中数据的变化,并 return 一个计算后的新值,
供组件渲染 DOM 时使用。
2. 如何声明计算属性
计算属性需要以 function 函数的形式声明到组件的 computed 选项中,示例代码如下:
<!-- 直接以属性的方式使用 -->
<template>
{{ count }}
</template>
<script>
export default {
computed:{
<!-- 以函数的方式定义 -->
count(n) {
return n+2
}
})
return i
},
}
}
</script>
注意:计算属性侧重于得到一个计算的结果,因此计算属性中必须有 return 返回值!
3. 计算属性的使用注意点
① 计算属性必须定义在 computed 节点中
② 计算属性必须是一个 function 函数
③ 计算属性必须有返回值
④ 计算属性必须当做普通属性使用
4. 计算属性 vs 方法
相对于方法来说,计算属性会缓存计算的结果,只有计算属性的依赖项发生变化时,才会重新进行运算。因此
计算属性的性能更好。使用方法,在模板中使用多次会计算多次,而计算属性只计算一次,后面调用缓存。
5. 计算属性案例
案例需求,使用计算属性动态计算:
① 已勾选的商品总个数
② 已勾选的商品总价
③ 结算按钮的禁用状态
结算区域代码:
<!-- 结算区域 -->
<div class="settle-box">
<!-- TODO: 1. 动态计算已勾选的商品的总数量 -->
<span>总数量:{{ count }}</span>
<!-- TODO: 2. 动态计算已勾选的商品的总价 -->
<span>总价:{{ price }}元</span>
<!-- TODO: 3. 动态计算按钮的禁用状态 -->
<button type="button" style="background-color: #f40; border: 1px #f40 solid;" class="btn btn- primary" :disabled="isdisabled">结算</button>
</div>
计算属性相关代码:
<script>
export default {
computed:{
// 已勾选商品的总数量
count(x) {
let i = 0
this.fruitlist.forEach(x=>{
if(x.state === true){
i += x.count
}
})
return i
},
// 已勾选商品的总价格
price(x) {
let p = 0
this.fruitlist.forEach(x=>{
if(x.state === true){
p += x.price*x.count
}
})
return p
},
// 结算按钮是否禁用
isdisabled(){
return this.price === 0
}
},
}
完整代码-FruitList.vue:
<template>
<div class="fruit-list-container">
<!-- 水果列表 -->
<div class="fruit-list">
<!-- 水果的 item 项 -->
<div class="fruit-item" v-for="item in fruitlist" :key="item.id">
<div class="left">
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" :id="item.id" v-model="item.state" />
<label class="custom-control-label" :for="item.id">
<!-- 水果图片 -->
<img :src="item.pic" alt="" class="thumb" />
</label>
</div>
</div>
<div class="right">
<!-- 水果名称 -->
<div class="top">{{ item.fruit }}</div>
<div class="bottom">
<!-- 水果单价 -->
<span class="price">¥{{ item.price }}</span>
<div class="btns">
<!-- 水果数量 -->
<button type="button" class="btn btn-light" @click="onSubClick(item.id)">-</button>
<span class="count">{{ item.count }}</span>
<button type="button" class="btn btn-light" @click="onAddClick(item.id)">+</button>
</div>
</div>
</div>
</div>
</div>
<!-- 结算区域 -->
<div class="settle-box">
<!-- TODO: 1. 动态计算已勾选的商品的总数量 -->
<span>总数量:{{ count }}</span>
<!-- TODO: 2. 动态计算已勾选的商品的总价 -->
<span>总价:{{ price }}元</span>
<!-- TODO: 3. 动态计算按钮的禁用状态 -->
<button type="button" style="background-color: #f40; border: 1px #f40 solid;" class="btn btn-primary" :disabled="isdisabled">结算</button>
</div>
</div>
</template>
<script>
export default {
name: 'FruitList',
data() {
return {
fruitlist: [
{ id: 1, fruit: '香橼', pic: '/src/assets/images/1.jpg', price: 5, count: 1, state: true },
{ id: 2, fruit: '柚子', pic: '/src/assets/images/2.jpg', price: 4.5, count: 1, state: false },
{ id: 3, fruit: '橘子', pic: '/src/assets/images/3.jpg', price: 3, count: 1, state: false },
{ id: 4, fruit: '橙子', pic: '/src/assets/images/4.jpg', price: 6, count: 1, state: false },
{ id: 5, fruit: '粑粑柑', pic: '/src/assets/images/5.jpg', price: 6.5, count: 1, state: false },
{ id: 6, fruit: '柠檬', pic: '/src/assets/images/6.jpg', price: 4, count: 1, state: false },
{ id: 7, fruit: '青柠', pic: '/src/assets/images/7.jpg', price: 5.2, count: 1, state: false },
],
}
},
computed:{
// 已勾选商品的总数量
count(x) {
let i = 0
this.fruitlist.forEach(x=>{
if(x.state === true){
i += x.count
}
})
return i
},
// 已勾选商品的总价格
price(x) {
let p = 0
this.fruitlist.forEach(x=>{
if(x.state === true){
p += x.price*x.count
}
})
return p
},
// 结算按钮是否禁用
isdisabled(){
return this.price === 0
}
},
methods: {
// 点击了数量 -1 按钮
onSubClick(id) {
const findResult = this.fruitlist.find(x => x.id === id)
if (findResult && findResult.count > 1) {
findResult.count--
}
},
// 点击了数量 +1 按钮
onAddClick(id) {
const findResult = this.fruitlist.find(x => x.id === id)
if (findResult) {
findResult.count++
}
},
},
}
</script>
<style lang="less" scoped>
.fruit-list-container {
padding-bottom: 50px;
}
.fruit-item {
display: flex;
padding: 10px;
& + .fruit-item {
border-top: 1px solid #efefef;
}
.left {
margin-right: 10px;
.thumb {
width: 100px;
height: 100px;
}
}
.right {
display: flex;
flex: 1;
flex-direction: column;
justify-content: space-between;
.top {
font-weight: bold;
font-size: 13px;
}
.bottom {
display: flex;
justify-content: space-between;
align-items: center;
.price {
font-size: 13px;
font-weight: bold;
color: red;
}
.btns {
display: flex;
align-items: center;
.count {
display: inline-block;
width: 28px;
text-align: center;
}
}
}
}
}
.custom-control-label::before,
.custom-control-label::after {
top: 47px;
border-radius: 10px !important;
}
.settle-box {
height: 50px;
position: fixed;
bottom: 0;
left: 0;
width: 100%;
background-color: #fff;
border-top: 1px solid #efefef;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 10px;
}
</style>
完整代码-MyHeader.vue
<template>
<div class="header-container" :style="{ backgroundColor: bgcolor, color: color }">
{{title || 'Header 组件'}}
</div>
</template>
<script>
export default {
name: 'MyHeader',
props: ['title', 'bgcolor', 'color']
}
</script>
<style lang="less" scoped>
.header-container {
height: 45px;
background-color: pink;
text-align: center;
line-height: 45px;
position: fixed;
top: 0;
left: 0;
width: 100%;
z-index: 999;
}
</style>
完整代码-App.vue
<template>
<div class="app-container">
<my-header title="水果列表" color="white" bgcolor="#f40"></my-header>
<fruit-list></fruit-list>
</div>
</template>
<script>
import MyHeader from './components/my-header/MyHeader.vue'
import FruitList from './components/fruit-list/FruitList.vue'
export default {
name: 'MyApp',
components: {
MyHeader,
FruitList,
},
}
</script>
<style lang="less" scoped>
.app-container {
padding-top: 45px;
}
</style>
完整打包源代码下载:
https://gitee.com/xingyueqianduan/vuecomputedfruit
写在最后
✨个人笔记博客✨
星月前端博客
✨原创不易,还希望各位大佬支持一下
👍 点赞,你的认可是我创作的动力!
⭐️ 收藏,你的青睐是我努力的方向!
✏️评论,你的意见是我进步的财富!
更多推荐
已为社区贡献9条内容
所有评论(0)