4.Vue3 Computed计算属性

185 阅读1分钟

computed计算属性

顾名思义,首先它是一种属性,其次它有“计算”这个特殊性质。每次取得它的值的时候,它并不像普通属性那样直接返回结果,而是经过一系列的计算之后再返回结果。 同时只要在它的当中里引用了 data 中的某个属性,当这个属性发生变化时,计算属性仿佛可以嗅探到这个变化,并自动重新执行。

计算属性和方法的区别:

  1. 计算属性是基于它们的依赖进行缓存的。计算属性只有在它的相关依赖发生改变时才会重新求值。
  2. 方法绑定数据只要被调用,方法将总会再次执行函数。
  3. 计算属性相对于方法在处理特定场合下节省资源性能

计算属性和侦听器的区别:

  1. 当watch监听的值发生改变就会被调用,watch可以在数据变化时做一些异步处理或者开销大的操作
  2. 计算属性是计算依赖的值,当依赖的值发生改变才会触发。
<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>