不灭的焱

革命尚未成功,同志仍须努力下载JDK17

作者:Albert.Wen  添加时间:2023-10-06 23:35:44  修改时间:2024-05-14 12:02:40  分类:前端/Vue/Node.js  编辑

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

 

 

摘自:

  1. https://blog.csdn.net/qq_61950936/article/details/126362958