在 Vue 3 中,侦听器是一种响应式特性,允许你观察和响应 Vue 实例上的数据变动。Vue 提供了 watch
和 watchEffect
两个函数来创建侦听器。
1、watch
侦听器
watch
是一个用于侦听特定数据源变化的函数。它允许你指定一个或多个数据源,并在这些数据源变化时执行回调函数。watch
通常用于侦听响应式状态的变化,并在变化发生时执行副作用。
特点:
- 懒执行:
watch
只有在被侦听的响应式数据变化时才会执行回调函数。 - 精确侦听:你可以精确指定要侦听的数据源,
watch
会确保只有在这些数据源变化时才触发回调。 - 可停止:
watch
返回一个停止侦听的函数,你可以在需要时停止侦听。
(1)、基本用法
<script setup>
import { ref, watch } from 'vue';
const state = ref(0);
const newstate = ref(0);
const oldtate = ref(0);
// 创建侦听器
watch(() => state.value, (newValue, oldValue) => {
newstate.value = newValue;
oldtate.value = oldValue;
});
// 定义事件处理函数
function handleClick() {
state.value = 10
}
</script>
<template>
<span> Selected: {{ newstate + "/" + oldtate}}</span>
<button @click="handleClick">Click me</button>
</template>
这段代码演示了如何在 Vue 3 中使用 <script setup>
语法来创建响应式状态和侦听器。当状态 state
发生变化时,侦听器会更新 newstate
和 oldtate
的值,并且在模板中显示这些变化。点击按钮会触发 handleClick
函数,该函数更新 state
的值,从而触发侦听器的回调函数。
(2)、侦听多个源
<script setup>
import { ref, watch } from 'vue';
const firstName = ref('John');
const lastName = ref('Doe');
const firstNewName = ref('John');
const lastnewName = ref('Doe');
watch([firstName, lastName], ([newFirstName, newLastName], [oldFirstName, oldLastName]) => {
console.log(`Name changed from ${oldFirstName} ${oldLastName} to ${newFirstName} ${newLastName}`);
firstNewName.value = newFirstName;
lastnewName.value = newLastName;
});
// 定义事件处理函数
function handleClick() {
firstName.value ='111111'
lastName.value ='222222'
}
</script>
<template>
<span> Selected: {{ firstNewName + "/" + lastnewName}}</span>
<p> </p>
<button @click="handleClick">Click me</button>
</template>
点击按钮前:
点击按钮后:
(3)、侦听数据源类型
watch
的第一个参数可以是不同形式的“数据源”:
它可以是一个 ref (包括计算属性)、一个响应式对象、一个getter 函数、或多个数据源组成的数组:
const x = ref(0)
const y = ref(0)
// 单个 ref
watch(x, (newX) => {
console.log(`x is ${newX}`)
})
// getter 函数
watch(
() => x.value + y.value,
(sum) => {
console.log(`sum of x + y is: ${sum}`)
}
)
// 多个来源组成的数组
watch([x, () => y.value], ([newX, newY]) => {
console.log(`x is ${newX} and y is ${newY}`)
})
(4) 、一次性侦听器
- 仅支持 3.4 及以上版本
每当被侦听源发生变化时,侦听器的回调就会执行。
如果希望回调只在源变化时触发一次,请使用 once: true
选项。
watch(
source,
(newValue, oldValue) => {
// 当 `source` 变化时,仅触发一次
},
{ once: true }
)
2、watchEffect
侦听器
watchEffect
是一个用于侦听多个响应式数据源变化的函数。它立即执行回调函数,并在其依赖的响应式数据变化时重新执行。
特点:
-
即时执行:
watchEffect
在创建时立即执行回调函数,而不仅仅是在依赖的数据变化时。 -
依赖跟踪:
watchEffect
会自动追踪其回调函数中使用的所有响应式数据。 -
自动清理:
watchEffect
在组件卸载时自动停止侦听,无需手动停止。
<script setup>
import { ref, watchEffect } from 'vue';
const x = ref(0);
const y = ref(0);
const xNewsum = ref(0);
// 创建侦听器
watchEffect(() => {
xNewsum.value = x.value + y.value ;
});
// 定义事件处理函数
function handleClick() {
x.value =134
y.value =134
}
</script>
<template>
<span> xNewsum: {{ xNewsum}}</span>
<p> </p>
<button @click="handleClick">Click me</button>
</template>
启动时, 立即执行:
当点击按钮后,更新数据:
3 、选择 watch
还是 watchEffect
-
如果你需要在数据变化时执行副作用,并且希望副作用只在数据变化时触发,使用
watch
。 -
如果你需要立即执行副作用,并且副作用依赖于多个响应式数据源,使用
watchEffect
。 -
如果你的副作用逻辑较为简单,或者你希望副作用能够立即执行,
watchEffect
可能是更好的选择。 -
如果你需要更精细的控制副作用的执行时机,或者你需要在副作用执行前后进行额外的操作,
watch
可能更适合你的需求。
(1)、watch
的应用场景
侦听特定数据源的变化:
当你需要在特定的响应式数据变化时执行操作,比如表单验证、数据转换或者条件渲染。
import { ref, watch } from 'vue';
const username = ref('');
watch(username, (newValue, oldValue) => {
if (newValue !== oldValue) {
console.log(`Username changed from ${oldValue} to ${newValue}`);
}
});
条件渲染:
当你需要根据数据的变化来决定是否执行某些操作,例如,只有在某个条件满足时才执行副作用。
import { ref, watch } from 'vue';
const isPremiumUser = ref(false);
watch(isPremiumUser, (newStatus) => {
if (newStatus) {
console.log('User is now a premium user');
}
});
依赖多个数据源:
当你需要侦听多个数据源,并在任何一个数据源变化时执行操作。
import { ref, watch } from 'vue';
const firstName = ref('');
const lastName = ref('');
watch([firstName, lastName], ([newFirstName, newLastName], [oldFirstName, oldLastName]) => {
console.log(`Name changed from ${oldFirstName} ${oldLastName} to ${newFirstName} ${newLastName}`);
});
(2)、watchEffect
的应用场景
立即执行副作用:
当你需要在组件初始化时立即执行副作用,并且副作用依赖于多个响应式数据源。
import { ref, watchEffect } from 'vue';
const count = ref(0);
watchEffect(() => {
console.log(`Count is now ${count.value}`);
});
复杂的依赖跟踪:
当你的副作用依赖于多个响应式数据源,并且这些依赖关系在副作用函数中不明显时。
import { ref, computed, watchEffect } from 'vue';
const firstName = ref('');
const lastName = ref('');
const fullName = computed(() => `${firstName.value} ${lastName.value}`);
watchEffect(() => {
console.log(`Full name is now ${fullName.value}`);
});
自动清理副作用:
当你需要在副作用中设置事件监听器或其他需要清理的资源,并且希望这些资源在组件卸载时自动清理。
import { onMounted, onUnmounted, watchEffect } from 'vue';
watchEffect(() => {
const handleResize = () => {
console.log('Window resized');
};
window.addEventListener('resize', handleResize);
onUnmounted(() => {
window.removeEventListener('resize', handleResize);
});
});
```<br/>