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

相关推荐
庸俗今天不摸鱼11 分钟前
【万字总结】前端全方位性能优化指南(十)——自适应优化系统、遗传算法调参、Service Worker智能降级方案
前端·性能优化·webassembly
QTX1873011 分钟前
JavaScript 中的原型链与继承
开发语言·javascript·原型模式
黄毛火烧雪下18 分钟前
React Context API 用于在组件树中共享全局状态
前端·javascript·react.js
Apifox28 分钟前
如何在 Apifox 中通过 CLI 运行包含云端数据库连接配置的测试场景
前端·后端·程序员
一张假钞31 分钟前
Firefox默认在新标签页打开收藏栏链接
前端·firefox
高达可以过山车不行31 分钟前
Firefox账号同步书签不一致(火狐浏览器书签同步不一致)
前端·firefox
m0_5937581032 分钟前
firefox 136.0.4版本离线安装MarkDown插件
前端·firefox
掘金一周35 分钟前
金石焕新程 >> 瓜分万元现金大奖征文活动即将回归 | 掘金一周 4.3
前端·人工智能·后端
三翼鸟数字化技术团队1 小时前
Vue自定义指令最佳实践教程
前端·vue.js
Jasmin Tin Wei1 小时前
蓝桥杯 web 学海无涯(axios、ecahrts)版本二
前端·蓝桥杯