Vue3 + vite + Ts + computed(计算属性) 和 watch(侦听器)的简单使用方法

12 篇文章 1 订阅
6 篇文章 1 订阅

Vue3 + vite + Ts + computed(计算属性) 和 watch(侦听器)的简单使用方法

1、computed :计算属性

  • 计算属性就是当依赖的值发生变化的时候,才会触发他的更改,如果依赖的值,不发生变化的时候,使用的是缓存中的属性值。
  • 简单使用方法,示例代码如下:
 import { ref, reactive, computed } from 'vue'

// 计算总价格,通过 computed 计算属性来计算
const totalPrice = computed(() => {
  return goodList.reduce((total: number, item: goodList) => {
    return total + item.good_count * item.good_price
  }, 0)
})
  • 简单购物车案例,代码如下:
<template>
  <div>
    <div>
      <input type="text" v-model="keyword" placeholder="搜索">
    </div>
    <div style="margin-top:15px;">
      <table>
        <thead>
          <tr>
            <th>物品名称</th>
            <th>物品单价</th>
            <th>物品数量</th>
            <th>物品总价</th>
            <th>操作</th>
          </tr>
        </thead>
        <tbody>
          <tr v-for="(item, index) in searchGoogList" :key="item.id">
            <td>{{ item.good_name }}</td>
            <td>{{ item.good_price }}</td>
            <td>
              <button @click="item.good_count > 1 ? item.good_count-- : null">-</button>
              {{ item.good_count }}
              <button @click="item.good_count < 99 ? item.good_count++ : null">+</button>
            </td>
            <td>{{ item.good_price * item.good_count }}</td>
            <td>
              <button @click="deleteHandle(index)">删除</button>
            </td>
          </tr>
          <tr>
            <td colspan="5" align="right">总价:{{ totalPrice }}</td>
          </tr>
        </tbody>
      </table>
    </div>
  </div>
</template>
<script setup lang='ts'>
import { ref, reactive, computed } from 'vue'

// 搜索关键字
const keyword = ref<string>("")

// 物品列表
const goodList = reactive([{
  id: 1,
  good_name: '小满的绿帽子',
  good_price: 500,
  good_count: 2
}, {
  id: 2,
  good_name: '小满的红衣服',
  good_price: 10,
  good_count: 1
}, {
  id: 3,
  good_name: '小满的黑袜子',
  good_price: 120,
  good_count: 1
}])

// 搜索方法
const searchGoogList = computed(() => {
  return goodList.filter((item: goodList) => {
    return item.good_name.includes(keyword.value)
  })
})

// 计算总价格,通过 computed 计算属性来计算
const totalPrice = computed(() => {
  return goodList.reduce((total: number, item: goodList) => {
    return total + item.good_count * item.good_price
  }, 0)
})

// 删除方法
const deleteHandle = (index: number) => {
  goodList.splice(index, 1)
}

</script>
<style scoped>
table,
thead tr th,
tbody tr td {
  border-collapse: collapse;
  border: 1px pink solid;
}

th,
td {
  padding: 5px 20px;
}
</style>

注意:这么定义的计算属性是只读的,不能修改

2、watch:侦听器

  • 作用:监视数据的变化(和 Vue2 中的 watch 作用一致)
  • 特点:Vue3 中的 watch 只能监视以下四种数据:
    • 1、ref 定义的数据
    • 2、reactive 定义的数据
    • 3、函数返回一个值
    • 4、一个包含上述内容的数组

2.1、情况一

  • 监听 ref 定义的【基本类型】数据:直接写数据名即可,监视的是其 value 值的改变(并停止监听)。
<template>
  价格 :<input v-model="price" type="text" /><br />
  <button @click="addPriceHandle">增长</button>
</template>

<script setup lang="ts">
import { ref, watch } from "vue";

let price = ref<number>(0);

/**
 * 增长价格方法
 */
const addPriceHandle = () => {
  price.value += 1;
};

// 监听 message 变量
const stopWatch = watch(price, (newVal: number, oldVal: number) => {
  console.log("当前价格:" + newVal);
  if (newVal >= 10) {
    // 停止监听
    stopWatch();
  }
});
</script>
<style scoped></style>

2.2、情况二

  • 监听 ref 定义的【对象类型】数据:直接写数据名,监视的是对象的【地址值】,若想监视对象内部的数据,要手动开启深度监视

注意:
1、若修改的是 ref 定义的对象中的属性,newValueoldValue 都是新值,因为它们是同一个对象。
2、若修改整个 ref 定义的对象,newValue 是新值,oldValue 是旧值,因为不是同一个对象了。

<template>
  姓名:{{ person.username }}<br />
  年龄:{{ person.age }}<br />
  <button @click="editUserNameHandle">修改姓名</button>
  <button @click="editAgeHandle">修改年龄</button>
  <button @click="editHandle">修改对象</button>
</template>

<script setup lang="ts">
import { ref, watch } from "vue";

const person = ref({
  username: "人类",
  age: 30,
});

/**
 * 修改姓名方法
 */
const editUserNameHandle = () => {
  person.value.username += "~";
};

/**
 * 修改姓名方法
 */
const editAgeHandle = () => {
  person.value.age += 1;
};

/**
 * 修改整个对象
 */
const editHandle = () => {
  person.value = {
    username: "近战法师 - 刘铁柱",
    age: 50,
  };
};

/**
 * 监听对象:监听 ref 定义的【对象类型】数据,监听的是对象的地址值
 */
watch(
  person,
  (newVal: any, oldVal: any) => {
    console.log(newVal);
    console.log(oldVal);
  }
);
</script>

<style lang="scss" scoped></style>
  • 深度侦听,示例代码如下:
<template>
  姓名:{{ person.username }}<br />
  年龄:{{ person.age }}<br />
  <button @click="editUserNameHandle">修改姓名</button>
  <button @click="editAgeHandle">修改年龄</button>
  <button @click="editHandle">修改对象</button>
</template>

<script setup lang="ts">
import { ref, watch } from "vue";

const person = ref({
  username: "人类",
  age: 30,
});

/**
 * 修改姓名方法
 */
const editUserNameHandle = () => {
  person.value.username += "~";
};

/**
 * 修改姓名方法
 */
const editAgeHandle = () => {
  person.value.age += 1;
};

/**
 * 修改整个对象
 */
const editHandle = () => {
  person.value = {
    username: "近战法师 - 刘铁柱",
    age: 50,
  };
};

/**
 * 监听对象:监听 ref 定义的【对象类型】数据,监听的是对象的地址值,若想监听对象内部属性的变化,需要手动开启深度监听
 */
watch(
  person,
  (newVal: any, oldVal: any) => {
    console.log(newVal);
    console.log(oldVal);
  },
  {
    deep: true,	// 深度监听
    immediate: true,  // 立即监听
  }
);
</script>

<style lang="scss" scoped></style>

2.3、情况三

  • 监听 reactive 定义的【对象类型】数据,且默认开启了深度监听。
  • 简单例子:
<template>
  姓名:{{ person.username }}<br />
  年龄:{{ person.age }}<br />
  <button @click="editUserNameHandle">修改姓名</button>
  <button @click="editAgeHandle">修改年龄</button>
  <button @click="editHandle">修改对象</button>
</template>

<script setup lang="ts">
import { reactive, watch } from "vue";

const person = reactive({
  username: "人类",
  age: 30,
});

/**
 * 修改姓名方法
 */
const editUserNameHandle = () => {
  person.username += "~";
};

/**
 * 修改姓名方法
 */
const editAgeHandle = () => {
  person.age += 1;
};

/**
 * 修改整个对象
 */
const editHandle = () => {
  Object.assign(person, {
    username: "近战法师 - 刘铁柱",
    age: 60,
  });
};

/**
 * 监听对象:监听 reactive 定义的【对象类型】数据
 */
watch(person, (newVal: any, oldVal: any) => {
  console.log(newVal);
  console.log(oldVal);
});
</script>

<style lang="scss" scoped></style>

2.4、情况四

  • 监听响应式对象中的某个属性,且该属性时基本类型的,要写成函数式
  • 监听 refreactive 定义的【对象类型】数据中的某个属性,注意点如下:
    • 1、若该属性值不是【对象类型】,需要写成函数形式。
    • 2、若该属性值是依然是【对象类型】,可直接编,也可写成函数,建议写成函数。
  • 简单例子:
<template>
  姓名:{{ person.username }}<br />
  年龄:{{ person.age }}<br />
  汽车:{{ person.car.c1 + "," + person.car.c2 }}<br />
  <br />
  <button @click="editUsernameHandle">修改姓名</button>
  <button @click="editAgeHandle">修改年龄</button>
  <button @click="editC1Handle">修改第一台车</button>
  <button @click="editC2Handle">修改第二台车</button>
  <button @click="editCHandle">修改所有车</button>
</template>

<script setup lang="ts">
import { reactive, watch } from "vue";

const person = reactive({
  username: "张三",
  age: 60,
  car: {
    c1: "奔驰",
    c2: "宝马",
  },
});

/**
 * 修改姓名
 */
function editUsernameHandle() {
  person.username += "~";
}

/**
 * 监听姓名变化,只监听姓名
 */
watch(
  () => person.username,
  (newVal, oldVal) => {
    console.log(newVal);
    console.log(oldVal);
  }
);

/**
 * 修改年龄
 */
function editAgeHandle() {
  person.age += 1;
}

/**
 * 修改第一台车
 */
function editC1Handle() {
  person.car.c1 += 1;
}

/**
 * 修改第二台车
 */
function editC2Handle() {
  person.car.c2 += 1;
}

/**
 * 修改所有车
 */
function editCHandle() {
  Object.assign(person.car, {
    c1: "劳斯莱斯",
    c2: "布加迪",
  });
}

/**
 * 监听所有汽车
 */

watch(
  () => person.car,
  (newVal, oldVal) => {
    console.log(newVal);
    console.log(oldVal);
  },
  {
    deep: true,
  }
);
</script>

<style lang="scss" scoped></style>

结论:监听的要是对象里的属性,那么最好写函数式,。
注意点:若是对象监听的是地址值,需要关注对象内部,需要手动开启深度监听。

2.5、情况五

  • 监听上述的多个数据
  • 简单例子:
<template>
  姓名:{{ person.username }}<br />
  年龄:{{ person.age }}<br />
  汽车:{{ person.car.c1 + "," + person.car.c2 }}<br />
  <br />
  <button @click="editUsernameHandle">修改姓名</button>
  <button @click="editAgeHandle">修改年龄</button>
  <button @click="editC1Handle">修改第一台车</button>
  <button @click="editC2Handle">修改第二台车</button>
  <button @click="editCHandle">修改所有车</button>
</template>

<script setup lang="ts">
import { reactive, watch } from "vue";

const person = reactive({
  username: "张三",
  age: 60,
  car: {
    c1: "奔驰",
    c2: "宝马",
  },
});

/**
 * 修改姓名
 */
function editUsernameHandle() {
  person.username += "~";
}

/**
 * 修改年龄
 */
function editAgeHandle() {
  person.age += 1;
}

/**
 * 修改第一台车
 */
function editC1Handle() {
  person.car.c1 += 1;
}

/**
 * 修改第二台车
 */
function editC2Handle() {
  person.car.c2 += 1;
}

/**
 * 修改所有车
 */
function editCHandle() {
  Object.assign(person.car, {
    c1: "劳斯莱斯",
    c2: "布加迪",
  });
}

/**
 * 监听第一台车和姓名
 */

watch(
  [() => person.car.c1, () => person.username],
  (newVal, oldVal) => {
    console.log(newVal);
    console.log(oldVal);
  }
);
</script>

<style lang="scss" scoped></style>
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

W.Y.B.G

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值