在 Vue 3 中,watchEffect
是一个用于监听响应式数据变化的 API。它可以在函数内部自动跟踪数据的依赖,并在依赖变化时重新运行函数。
watchEffect
的作用以及各个参数的功能讲解:
watchEffect(effect: (onInvalidate: InvalidateCbRegistrator) => void | (() => void) | Promise, options?: WatchEffectOptions): WatchStopHandle
effect
:要监听的响应式数据以及需要执行的副作用函数。effect
函数接收一个onInvalidate
回调函数作为参数,用于在effect
的依赖发生变化时执行清理函数。effect
函数可以返回一个清理函数,也可以返回一个 Promise,Promise 完成时执行的函数也会被视为清理函数。如果effect
函数中使用的数据没有在响应式对象中被引用,那么watchEffect
不会监听到这些数据的变化。options
:监听选项对象,可选。可以用来配置监听的行为,例如deep
、flush
等选项。具体的选项请参考下面的讲解。- 返回值:一个函数,调用它可以停止监听。
WatchEffectOptions
watchEffect
函数接受一个可选的选项对象,用于配置监听行为。以下是 WatchEffectOptions
对象的属性及其功能:
lazy
:是否延迟执行effect
函数。如果设置为true
,则在首次调用watchEffect
时不会执行effect
函数,只有在其依赖发生变化时才会执行。默认为false
。deep
:是否深度监听对象和数组的变化,默认为false
。如果设置为true
,则会递归监听对象和数组中的所有属性。flush
:何时执行回调函数。默认为'pre'
,表示在响应式数据变化后立即执行回调函数,但在同一事件循环中的其他变化不会触发回调函数。如果设置为'post'
,则会在同一事件循环中的所有变化都发生后执行回调函数。
例如,以下代码使用 watchEffect
监听 message
的变化,并在变化时执行回调函数。
import { watchEffect } from 'vue';watchEffect(() => { console.log(`message 变为 ${message}`);});
下面是一个简单的例子,演示了如何使用 watchEffect
监听响应式数据变化:
输入框的值为:{{ message }}
import { defineComponent, ref, watchEffect } from 'vue';export default defineComponent({ setup() { const message = ref(''); watchEffect(() => { console.log(`message 值改变为:${message.value}`); }); return { message }; }});在这个例子中,我们使用
ref
函数定义了一个名为message
的响应式数据,并将其初始化为空字符串。我们使用watchEffect
函数监听message
的变化,并在函数内部打印出message
的值。因为watchEffect
函数会自动跟踪message
的依赖,所以当用户在输入框中输入内容时,watchEffect
函数就会重新运行,打印出新的message
值。需要注意的是,
watchEffect
函数的回调函数不需要显式地指定依赖项,它会自动跟踪回调函数内部使用到的所有响应式数据。因此,当你使用watchEffect
函数时,不需要再使用watch
函数或computed
函数来监听数据变化。但是,如果你需要监听某个特定的响应式数据变化,可以在回调函数中使用该数据,这样watchEffect
就会自动跟踪它。
watchEffect
函数的返回值是一个用于停止监听的函数。当你调用这个函数时,watchEffect
就会停止监听响应式数据的变化。以下是一个示例,演示如何使用
watchEffect
函数的返回值停止监听:输入框的值为:{{ message }}
import { defineComponent, ref, watchEffect } from 'vue';export default defineComponent({ setup() { const message = ref(''); const stopWatching = watchEffect(() => { console.log(`message 值改变为:${message.value}`); }); function stopWatching() { stopWatching(); } return { message, stopWatching }; }});在这个例子中,我们定义了一个名为
stopWatching
的函数,它调用了watchEffect
函数的返回值,从而停止了监听。我们在模板中添加了一个按钮,当用户点击它时,就会调用stopWatching
函数,从而停止监听message
的变化。watch的作用以及各个参数的功能讲解:
watch
是 Vue 3 中用于监听响应式数据变化的 API,它能够在响应式数据发生变化时执行回调函数。以下是watch
函数的参数及其功能:
watch(source: string | Function | Ref, callback: Function, options?: WatchOptions): WatchStopHandle
source
:要监听的响应式数据,可以是一个字符串(表示要监听的数据在组件实例中的属性名)、一个函数(返回要监听的数据)或一个 ref 对象。callback
:响应式数据变化时要执行的回调函数。回调函数接收两个参数:新值和旧值。options
:监听选项对象,可选。可以用来配置监听的行为,例如deep
、immediate
等选项。具体的选项请参考下面的讲解。- 返回值:一个函数,调用它可以停止监听。
WatchOptions
watch
函数接受一个可选的选项对象,用于配置监听行为。以下是WatchOptions
对象的属性及其功能:
immediate
:是否在监听开始时立即执行回调函数,默认为false
。deep
:是否深度监听对象和数组的变化,默认为false
。如果设置为true
,则会递归监听对象和数组中的所有属性。flush
:何时执行回调函数。默认为'pre'
,表示在响应式数据变化后立即执行回调函数,但在同一事件循环中的其他变化不会触发回调函数。如果设置为'post'
,则会在同一事件循环中的所有变化都发生后执行回调函数。onTrack
:监视属性被访问的函数。它接收一个追踪对象(TrackOpTypes)和追踪的目标对象(target)。可以用它来进行依赖追踪分析等操作。onTrigger
:监视属性被修改的函数。它接收一个触发对象(TriggerOpTypes)和触发的目标对象(target)。可以用它来进行调试、性能分析等操作。例如,以下代码监听
message
的变化,并在变化时执行回调函数,同时设置immediate
选项为true
,表示在组件挂载时立即执行一次回调函数。import { watch } from 'vue';watch( () => message, // 要监听的响应式数据 (newValue, oldValue) => { console.log(`message 从 ${oldValue} 变为 ${newValue}`); }, { immediate: true // 在组件挂载时立即执行回调函数 });
watchEffect
和watch
都是 Vue 3 中用于监听响应式数据变化的 API,它们之间的主要区别在于回调函数的类型和依赖项的声明方式。
watchEffect
接收一个不带参数的函数作为回调函数,在函数内部使用到的响应式数据变化时会自动触发回调函数。watchEffect
会自动追踪响应式数据的变化,并在每次变化时重新运行回调函数。watch
接收两个参数:第一个参数是要监听的响应式数据,第二个参数是一个回调函数。回调函数接收两个参数:新值和旧值。在响应式数据变化时,watch
会调用回调函数,并传入新值和旧值。可以通过第三个参数来声明要监听的选项,例如deep
、immediate
等。因为
watchEffect
自动追踪响应式数据的变化,所以它更适合处理简单的数据逻辑。如果需要监听特定的响应式数据或使用更高级的选项,可以使用watch
函数。使用watch
函数需要显式声明要监听的响应式数据,这可以使代码更具可读性。此外,watch
函数还支持声明多个要监听的响应式数据,这使得它可以处理更复杂的数据逻辑。总之,如果你只需要监听一些简单的响应式数据变化,可以使用
watchEffect
函数。如果需要监听特定的响应式数据或使用更高级的选项,可以使用watch
函数。以下是一个示例,演示
watchEffect
和watch
的差别:message1 值为:{{ message1 }}
message2 值为:{{ message2 }}
import { defineComponent, ref, watchEffect, watch } from 'vue';export default defineComponent({ setup() { const message1 = ref(0); const message2 = ref(0); // watchEffect 自动追踪响应式数据的变化 watchEffect(() => { console.log(`message1 值变为 ${message1.value}`); }); // watch 需要显式声明要监听的响应式数据 watch(message2, (newValue, oldValue) => { console.log(`message2 从 ${oldValue} 变为 ${newValue}`); }); function increment() { message1.value++; message2.value++; } return { message1, message2, increment }; }});在这个例子中,我们声明了两个响应式数据
message1
和message2
,并分别使用了watchEffect
和watch
监听它们的变化。watchEffect
自动追踪message1
的变化,并在变化时触发回调函数。而watch
则需要显式声明要监听的message2
,并在它的变化时触发回调函数。在点击按钮时,我们同时增加了message1
和message2
的值,从而触发了相应的回调函数。
watchEffect
和watch
的区别在于,watchEffect
监听的是一个函数的副作用,而watch
监听的是一个具体的响应式数据,因此watchEffect
不需要显式指定监听的数据,它会自动检测effect
函数中使用的响应式数据,并在其发生变化时执行回调函数。此外,watchEffect
也不需要手动停止监听,它会在组件卸载时自动停止监听。但是,watchEffect
不支持监听选项对象中的immediate
、onTrack
和onTrigger
属性。如果watch的监听对象是数组:
如果
watch
监听的是一个数组,则可以使用deep
选项来深度监听数组元素的变化。当deep
为true
时,watch
会递归监听数组中每个元素的变化。例如,以下代码使用
watch
监听list
数组的变化,并在变化时执行回调函数。import { watch } from 'vue';watch( () => list, (newList, oldList) => { console.log('list 变化了', newList, oldList); }, { deep: true });在上面的代码中,
watch
监听的是一个计算属性,计算属性返回list
数组。由于在监听选项中设置了deep: true
,因此watch
会深度监听list
数组,即递归监听数组中每个元素的变化。注意,当使用
deep
选项监听数组时,如果数组中的元素是对象,则需要确保这些对象是响应式的,否则无法监听它们的变化。如果数组中的元素不是响应式的对象,则无法监听其变化。