【vue】09.computer和watch的使用

一、引言

Vue 3作为前端框架的新贵,以其轻量、高效、易用等特点受到了广大开发者的喜爱。在Vue 3中,computed和watch是两个非常重要的响应式API,它们在处理数据变化和执行异步操作方面发挥着重要作用。本文将通过案例,由浅入深地介绍computed和watch的使用方法,帮助大家更好地掌握这两个API。

二、computed的用法

1.计算属性简介

计算属性(computed)用于声明依赖响应式数据的计算值。简单点来说就是,当依赖的数据发生变化时,计算属性会自动重新计算。

案例1:计算商品总价

购物车场景,我们需要计算商品的总价,这里使用computed计算总价:

javascript 复制代码
<template>
  <div>
    <p>商品单价:100元</p>
    <p>购买数量:{{ count }}</p>
    <p>商品总价:{{ totalPrice }}</p>
  </div>
</template>

<script>
import { ref, computed } from 'vue';

export default {
  setup() {
    const count = ref(1);
    const totalPrice = computed(() => {
      return count.value * 100;
    });

    return {
      count,
      totalPrice
    };
  }
};
</script>
  • const totalPrice = computed(() => { ... }); 这里定义了一个名为 totalPrice 的计算属性。**计算属性接收一个函数,该函数返回一个值。**这个值将根据依赖的响应式数据的变化自动更新。

  • 当 count 的值改变时,computed 属性会自动重新计算,如果依赖的数据没有发生变化,则不会重新计算。

  • computed 属性总是同步更新的。当依赖的响应式数据变化时,计算属性会立即更新其值。

简而言之,在模板中使用 {``{ totalPrice }} 时,Vue 会自动读取 totalPrice 计算属性的当前值并将其渲染到页面上。当用户修改购买数量(count)时,totalPrice 将自动更新,页面上的显示也会相应地改变。

案例2:计算a与b的和

javascript 复制代码
<template>
  <div>
    <p>数值 A: <input v-model.number="a" /></p>
    <p>数值 B: <input v-model.number="b" /></p>
    <p>总和:{{ sum }}</p>
  </div>
</template>

<script>
import { ref, computed } from 'vue';

export default {
  setup() {
    // 响应式引用:数值 A
    const a = ref(0);
    // 响应式引用:数值 B
    const b = ref(0);

    // 计算属性:数值 A 和 B 的和
    const sum = computed(() => a.value + b.value);

    // 暴露响应式引用和计算属性供模板使用
    return {
      a,
      b,
      sum
    };
  }
};
</script>
  • 在模板中,我们展示了两个输入框,用户可以在其中输入数值,而计算属性 sum 会实时更新显示这两个数值的和。

注意

1.默认情况下,计算属性是只读的。如果尝试修改一个计算属性,Vue 会给出警告。如果需要设置计算属性的值,可以提供一个包含 set 方法的对象,但通常推荐保持计算属性只读。

2.计算属性是同步更新的。如果计算属性依赖于异步数据,应当在数据到达后再进行计算属性的依赖更新。

2.computed的setter方法

computed默认只有getter方法,但我们可以为其添加setter方法,以便在修改计算属性时执行一些操作。

javascript 复制代码
const totalPrice = computed({
  get() {
    // 获取总价
    const priceWithoutDiscount = unitPrice.value * count.value;
    return priceWithoutDiscount * (1 - discount.value / 100);
  },
  set(newValue) {
    // 设置总价,例如根据新的总价来调整折扣
    // 注意:这个示例只是展示如何使用 set,实际上一般不会这样做
    const priceWithoutDiscount = unitPrice.value * count.value;
    discount.value = ((priceWithoutDiscount - newValue) / priceWithoutDiscount) * 100;
  }
});

三、watch的基本用法

1.侦听器简介

侦听器(watch)用于观察和响应 Vue 实例上的数据变动。当数据变化时,会触发对应的回调函数。

案例1:监听输入框内容变化

以下是一个监听输入框内容变化的示例:

javascript 复制代码
<template>
  <div>
    <input v-model="inputValue" />
    <p>输入内容:{{ inputValue }}</p>
  </div>
</template>

<script>
import { ref, watch } from 'vue';

export default {
  setup() {
    const inputValue = ref('');

    watch(inputValue, (newValue, oldValue) => {
      console.log(`输入内容从${oldValue}变为${newValue}`);
    });

    return {
      inputValue
    };
  }
};
</script>

2.watch的深度监听与立即执行

(1)深度监听

默认情况下,Vue 的 watch 不会侦听对象内部属性的变化。换句话说,如果只监听一个对象,而不是它的属性,那么只有当这个对象本身被替换时(即引用改变),watch 回调才会被触发。而我们希望能够侦听对象内部属性的变化,因此就出现了"深度监听"。

深度监听:当我们需要监听对象内部属性的变化时,可以设置deep选项为true。

案例1:

在这个例子中,我们将监听一个对象的内部属性变化。如果对象的属性发生变化,将会执行回调函数。

javascript 复制代码
<template>
  <div>
    <p>姓名:{{ userInfo.name }}</p>
    <p>年龄:{{ userInfo.age }}</p>
    <button @click="updateName">修改姓名</button>
    <button @click="updateAge">修改年龄</button>
  </div>
</template>

<script>
import { ref, watch } from 'vue';

export default {
  setup() {
    const userInfo = ref({
      name: '张三',
      age: 30
    });

    // 深度监听 userInfo 对象
    watch(userInfo, (newValue, oldValue) => {
      console.log('userInfo 对象发生变化:', newValue);
    }, {
      deep: true // 设置 deep 选项为 true,以深度监听对象内部属性的变化
    });

    // 修改姓名的方法
    function updateName() {
      userInfo.value.name = '李四';
    }

    // 修改年龄的方法
    function updateAge() {
      userInfo.value.age = 31;
    }

    return {
      userInfo,
      updateName,
      updateAge
    };
  }
};
</script>

(2)立即执行

那什么时候用立即执行?

  1. 当需要在组件初始化时执行某些依赖于响应式数据的操作时,使用 immediate: true 可以确保这些操作在组件的 mounted 钩子之前执行。

  2. 如果想要回调函数不仅应该在数据变化时执行,而且应该在一开始就根据当前值执行一次,那么 immediate: true 会很有用。

立即执行:默认情况下,watch会在被侦听的数据变化时执行回调函数。如果我们希望在组件初始化时立即执行回调函数,可以设置immediate选项为true。

案例1:立即执行
javascript 复制代码
<template>
  <div>
    <p>计数:{{ count }}</p>
    <button @click="increment">增加</button>
  </div>
</template>

<script>
import { ref, watch } from 'vue';

export default {
  setup() {
    const count = ref(0);

    // 监听 count 变化,并设置 immediate 选项为 true
    watch(count, (newValue, oldValue) => {
      console.log(`计数从 ${oldValue} 变为${newValue}`);
    }, {
      immediate: true // 设置 immediate 选项为 true,以在组件初始化时立即执行回调
    });

    // 增加 count 的方法
    function increment() {
      count.value++;
    }

    return {
      count,
      increment
    };
  }
};
</script>

五、使用场景辨析

|---------------------------------------------------------------------|------------------------------------------------------|
| 使用 computed 的场景 | 使用 watch 的场景 |
| 缓存计算结果:需要根据现有响应式数据派生出新数据时。 | 异步操作:需要在数据变化时执行异步操作或昂贵操作(如 API 调用)时。 |
| 同步操作:需要的数据依赖于其他响应式数据,并且这些依赖关系是同步的。 | 数据变化时的副作用:需要在数据变化时执行一些副作用时,比如更新另一个数据源或调用外部的回调函数。 |
| 模板内的复杂表达式 :模板中有复杂的表达式,为了保持模板的简洁性和可读性,可以将这些表达式移到 computed 属性中。 | 深度监听:需要监听对象内部属性的变化,或者数组的变化时。 |
| 复用逻辑 :如果计算逻辑需要在多个地方使用,使用 computed 可以避免代码重复。 | 立即执行:需要在侦听器创建时立即执行回调。 |

六、总结

本文通过案例由浅入深地介绍了Vue 3中computed和watch的使用方法。掌握这两个API的高级用法,有助于我们更好地处理响应式数据,提高开发效率。在实际项目中,应根据场景灵活运用computed和watch,充分发挥它们的优势。

相关推荐
Dream-Y.ocean1 小时前
鸿蒙PC平台宅匠 3D 室内设计适配实战:基于 Electron 壳方案的 Three.js 双渲染引擎与参数化户型编辑器开发
javascript·3d·harmonyos
Csvn2 小时前
性能监控
前端
Highcharts.js2 小时前
Highcharts Gantt使用符号的自定义数据标签开发甘特图示例
javascript·甘特图·highcharts·图表开发·实战代码·响应式图表
Csvn3 小时前
构建工具
前端
FRing033 小时前
vue2干货总结3(computed计算属性、watch监听器)
开发语言·前端·vue.js·vue2
Java小卷4 小时前
JuanForm vs FormCreate!Vue3 表单引擎联动配置 PK!
vue.js·低代码
kyriewen5 小时前
Skills 榜前 10 我全装了:只有 3 个能直接用
前端·javascript·程序员
IT_陈寒6 小时前
当Java的hashCode遇上Lombok,我的缓存被全清了
前端·人工智能·后端
工控丫丫6 小时前
帆软看板中经常使用的公式函数及经常搭的组合
前端·javascript·数据库
jerrywus6 小时前
我用 GPT-6.1-sol 做了台会讲解的 3D 售货机:60 罐饮料,一口没喝上
前端·agent·claude