【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,充分发挥它们的优势。

相关推荐
前端熊猫34 分钟前
transform学习
前端·学习·html
sun lover44 分钟前
electron快速上手
javascript·electron
GISer_Jing44 分钟前
React渲染流程与更新diff算法
前端·javascript·react.js
郑祎亦1 小时前
JavaWeb开发:HTML 页面与接口对接
前端·后端·java-ee·html
Au_ust1 小时前
css:感觉稍微高级一点的布局
前端·css
下页、再停留1 小时前
【前端】CSS修改div滚动条样式
前端·css
一晌贪欢i1 小时前
CSS中calc语法不生效
前端·css
前端白袍1 小时前
Vue:后端返回二进制文件,前端如何实现浏览器自动下载?
前端·javascript·vue.js
问道飞鱼1 小时前
【前端知识】简单讲讲什么是微前端
前端·微前端·qiankun·single-spa
大得3691 小时前
css水平居中+垂直居中
vue.js·react