vue3从精通到入门10:侦听器watch

watch 是一个用于观察和响应 Vue 组件中响应式数据变化的工具。当组件中的某个响应式数据发生变化时,watch 可以帮助你执行一些特定的操作或副作用(side effects),比如更新其他数据、执行异步请求、调用方法等。

watch的用法

1. 基本用法

你可以使用 watch 来监听单个数据属性的变化:

<template>  
  <input v-model="firstName" placeholder="Enter your first name">  
</template>  
  
<script setup>  
import { ref, watch } from 'vue';  
  
const firstName = ref('');  
  
watch(firstName, (newVal, oldVal) => {  
  console.log(`First name changed from ${oldVal} to ${newVal}`);  
  // 在这里可以执行一些副作用,例如异步请求等  
});  
</script>

2. 监听多个数据源

你也可以同时监听多个响应式数据的变化:

<template>  
  <div>  
    <input v-model="firstName" placeholder="Enter your first name">  
    <input v-model="lastName" placeholder="Enter your last name">  
  </div>  
</template>  
  
<script setup>  
import { ref, watch } from 'vue';  
  
const firstName = ref('');  
const lastName = ref('');  
  
watch([firstName, lastName], ([newFirstName, newLastName], [oldFirstName, oldLastName]) => {  
  console.log(`First name changed from ${oldFirstName} to ${newFirstName}`);  
  console.log(`Last name changed from ${oldLastName} to ${newLastName}`);  
});  
</script>

3. 深度监听对象

如果你想监听对象的内部属性变化,可以使用 deep 选项:

<template>  
  <input v-model="user.name" placeholder="Enter your name">  
</template>  
  
<script setup>  
import { ref, watch } from 'vue';  
  
const user = ref({ name: '' });  
  
watch(user, (newVal, oldVal) => {  
  console.log('User object changed:', newVal);  
}, { deep: true }); // 开启深度监听  
</script>

注意,深度监听可能会带来性能开销,因为它会递归地遍历对象的所有属性。因此,在可能的情况下,尽量避免使用深度监听,或者只监听对象中的特定属性。

4. 立即执行回调函数

默认情况下,watch 的回调函数在数据第一次变化时不会执行。如果你希望回调函数立即执行一次,可以设置 immediate 选项为 true

watch(firstName, (newVal, oldVal) => {  
  console.log(`First name is now: ${newVal}`);  
}, { immediate: true }); // 立即执行回调函数

5. 停止监听

watch 函数返回一个停止监听的函数,你可以调用这个函数来停止监听:

const stopWatch = watch(firstName, (newVal) => {  
  console.log(`First name is now: ${newVal}`);  
});  
  
// 停止监听  
stopWatch();

6. 监听组件的 props 或 $emit 事件

你也可以使用 watch 来监听组件的 props 或监听子组件通过 $emit 触发的事件:

<script setup>  
import { watch } from 'vue';  
  
const props = defineProps({  
  propToWatch: String  
});  
  
const emit = defineEmits(['updateValue']);  
  
watch(() => props.propToWatch, (newVal) => {  
  console.log(`propToWatch changed to: ${newVal}`);  
});  
  
watch(() => emit, (newVal, oldVal) => {  
  // 当子组件触发 'updateValue' 事件时,这里的回调函数会被调用  
  console.log('updateValue event emitted');  
}, { deep: true }); // 注意这里可能需要深度监听,取决于你的具体用例  
</script>

watch的使用场景

1. 异步数据获取

当某个数据属性变化时,你可能需要发送异步请求获取新数据。例如,用户在一个搜索框中输入内容时,你可能想根据输入内容实时搜索并显示结果。使用 watch 可以监听搜索框的值,并在其变化时发起搜索请求。

<template>  
  <input v-model="searchQuery" placeholder="Search...">  
  <div v-if="searchResults">{{ searchResults }}</div>  
</template>  
  
<script setup>  
import { ref, watch } from 'vue';  
import { fetchSearchResults } from './api';  
  
const searchQuery = ref('');  
const searchResults = ref(null);  
  
watch(searchQuery, async (newQuery) => {  
  const results = await fetchSearchResults(newQuery);  
  searchResults.value = results;  
});  
</script>

2. 复杂数据变化处理

当需要处理复杂数据结构的变化时,watch 可以帮助你执行相应的逻辑。例如,你可能有一个对象,其中包含了多个属性,你需要在这些属性变化时执行一些操作。

<template>  
  <div>  
    <!-- 渲染表单输入 -->  
  </div>  
</template>  
  
<script setup>  
import { ref, watch } from 'vue';  
  
const formData = ref({  
  name: '',  
  email: '',  
  address: {  
    street: '',  
    city: ''  
  }  
});  
  
watch(formData, (newFormData, oldFormData) => {  
  // 当 formData 对象的任何属性变化时,执行某些操作  
  // 例如,验证表单数据或准备提交  
}, { deep: true }); // 深度监听对象的变化  
</script>

3. 监听 props 或 $emit 事件

在组件中,你可能需要监听父组件传递的 props 的变化,或者在子组件触发 $emit 事件时执行某些操作。

<script setup>  
import { defineProps, defineEmits, watch } from 'vue';  
  
const props = defineProps({  
  propToWatch: String  
});  
  
const emit = defineEmits(['updateValue']);  
  
watch(() => props.propToWatch, (newVal) => {  
  // 当 propToWatch 变化时,执行操作  
});  
  
watch(() => emit, (newVal, oldVal) => {  
  // 当子组件通过 $emit 触发事件时,执行操作  
}, { deep: true }); // 注意深度监听可能需要根据具体场景使用  
</script>

4. 监听计算属性或方法的结果

虽然不常见,但有时你可能想监听一个计算属性或方法返回的结果的变化。这通常是因为计算属性或方法依赖于其他响应式数据,并且你希望在结果变化时执行某些操作。

<script setup>  
import { ref, computed, watch } from 'vue';  
  
const basePrice = ref(100);  
const discount = ref(0.1);  
  
const finalPrice = computed(() => basePrice.value * (1 - discount.value));  
  
watch(finalPrice, (newPrice) => {  
  // 当 finalPrice 计算结果变化时,执行操作  
});  
</script>

注意事项:

  • 当使用深度监听(deep: true)时,请注意性能影响,因为深度监听会递归地遍历对象的所有属性。如果可能,尽量避免深度监听,或者仅监听你关心的特定属性。
  • watch 应该在组件的 setup 函数中使用,以确保它能够在响应式数据变化时正确执行。
  • 在某些情况下,如果可以使用 computed 属性来派生新值,那么可能不需要使用 watchcomputed 属性会自动更新,并且它们的结果可以被直接用于模板中,而不需要在每次变化时执行额外的逻辑。

watch的函数原理

watch 的工作原理依赖于 Vue 3 的响应式系统。每个响应式引用(通过 ref 创建)或响应式对象(通过 reactive 创建)都有一个与之关联的依赖收集器。当我们在模板或计算属性中使用这些响应式数据时,Vue 会自动将这些依赖记录下来。当响应式数据变化时,Vue 会触发所有相关依赖的更新,这包括 watch 的回调函数。

  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值