Vue3中watch的最佳实践 您所在的位置:网站首页 vue3中reactive的用法 Vue3中watch的最佳实践

Vue3中watch的最佳实践

2024-02-21 00:26| 来源: 网络整理| 查看: 265

前言🌟

本文诣在帮大家彻底梳理Vue3中watch的用法。

首先,介绍Vue3的watch API的基本使用,然后介绍了watch在侦听单个数据源、多个数据源的注意事项,最后通过对比得出watch侦听引用类型数据源的最佳实践。

一、API介绍 watch(WatcherSource, Callback, [WatchOptions]) type WatcherSource = Ref | (() => T) interface WatchOptions extends WatchEffectOptions { deep?: boolean // 默认:false immediate?: boolean // 默认:false flush?: string // 默认:'pre' }

参数说明:

WatcherSource: 用于指定要侦听的响应式数据源。侦听器数据源可以是返回值的 getter 函数,也可以直接是 ref。

Callback: 执行的回调函数,可依次接收当前值newValue,先前值oldValue作为入参。

WatchOptions:deep、immediate、flush可选。

当需要对响应式对象进行深度监听时,设置deep: true。 默认情况下watch是惰性的,当我们设置immediate: true时,watch会在初始化时立即执行回调函数。 flush 选项可以更好地控制回调的时间。它可设置为 pre、post 或 sync。 默认值是 pre,指定的回调应该在渲染前被调用。 post 值是可以用来将回调推迟到渲染之后的。如果回调需要通过 $refs 访问更新的 DOM 或子组件,那么则使用该值。 如果 flush 被设置为 sync,一旦值发生了变化,回调将被同步调用(少用,影响性能)。 二、侦听单个数据源及停止侦听 import { watch, ref, reactive } from 'vue' // 侦听一个 getter const person = reactive({name: '小松菜奈'}) watch( () => person.name, (value, oldValue) => { console.log(value, oldValue) }, {immediate:true} ) person.name = '有村架纯' // 直接侦听ref const ageRef = ref(16) const stopAgeWatcher = watch(ageRef, (value, oldValue) => { console.log(value, oldValue) if (value > 18) { stopAgeWatcher() // 当ageRef大于18,停止侦听 } }) const changeAge = () => { ageRef.value += 1 }

未标题-3.gif

现象:配置了immediate:true的watch,在初始化时触发了一次watch的回调。我们连续点击增加年龄,当年龄的当前值大于18时,watch停止了侦听。

结论:侦听器数据源可以是返回值的 getter 函数,也可以直接是 ref。我们可以利用给watch函数取名字,然后通过执行名字()函数来停止侦听。

三、监听多个数据源 import {ref, watch, nextTick} from 'vue' const name = ref('小松菜奈') const age = ref(25) watch([name, age], ([name, age], [prevName, prevAge]) => { console.log('newName', name, 'oldName', prevName) console.log('newAge', age, 'oldAge', prevAge) }) // 如果你在同一个函数里同时改变这些被侦听的来源,侦听器只会执行一次 const change1 = () => { name.value = '有村架纯' age.value += 2 } // 用 nextTick 等待侦听器在下一步改变之前运行,侦听器执行了两次 const change2 = async () => { name.value = '新垣结衣' await nextTick() age.value += 2 }

未标题-4.gif

现象:以上,当我们在同一个函数里同时改变name和age两个侦听源,watch的回调函数只触发了一次;当我们在name和age的改变之间增加了一个nextTick,watch回调函数触发了两次。

结论:我们可以通过watch侦听多个数据源的变化。如果在同一个函数里同时改变这些被侦听的来源,侦听器只会执行一次。若要使侦听器执行多次,我们可以利用 nextTick ,等待侦听器在下一步改变之前运行。

四、侦听引用对象(数组Array或对象Object) ref定义数组:{{arrayRef}} reactive定义数组:{{arrayReactive}} 改变ref定义数组第一项 改变reactive定义数组第一项 import {ref, reactive, watch} from 'vue' const arrayRef = ref([1, 2, 3, 4]) const arrayReactive = reactive([1, 2, 3, 4]) // ref not deep, 不能深度侦听 const arrayRefWatch = watch(arrayRef, (newValue, oldValue) => { console.log('newArrayRefWatch', newValue, 'oldArrayRefWatch', oldValue) }) // ref deep, 深度侦听,新旧值一样 const arrayRefDeepWatch = watch(arrayRef, (newValue, oldValue) => { console.log('newArrayRefDeepWatch', newValue, 'oldArrayRefDeepWatch', oldValue) }, {deep: true}) // ref deep, getter形式 , 新旧值不一样 const arrayRefDeepGetterWatch = watch(() => [...arrayRef.value], (newValue, oldValue) => { console.log('newArrayRefDeepGetterWatch', newValue, 'oldArrayRefDeepGetterWatch', oldValue) }) // reactive,默认深度监听,可以不设置deep:true, 新旧值一样 const arrayReactiveWatch = watch(arrayReactive, (newValue, oldValue) => { console.log('newArrayReactiveWatch', newValue, 'oldArrayReactiveWatch', oldValue) }) // reactive,getter形式 , 新旧值不一样 const arrayReactiveGetterWatch = watch(() => [...arrayReactive], (newValue, oldValue) => { console.log('newArrayReactiveFuncWatch', newValue, 'oldArrayReactiveFuncWatch', oldValue) }) const changeArrayRef = () => { arrayRef.value[0] = 3 } const changeArrayReactive = () => { arrayReactive[0] = 6 }

未标题-2.gif

现象:当将引用对象采用ref形式定义时,如果不加上deep:true,watch是侦听不到值的变化的;而加上deep:true,watch可以侦听到数据的变化,但是当前值和先前值一样,即不能获取先前值。当将引用对象采用reactive形式定义时,不作任何处理,watch可以侦听到数据的变化,但是当前值和先前值一样。两种定义下,把watch的数据源写成getter函数的形式并进行深拷贝返回,可以在watch回调中同时获得当前值和先前值。

结论: 当我们使用watch侦听引用对象时

若使用ref定义的引用对象: 只要获取当前值,watch第一个参数直接写成数据源,另外需要加上deep:true选项 若要获取当前值和先前值,需要把数据源写成getter函数的形式,并且需对数据源进行深拷贝 若使用reactive定义的引用对象: 只要获取当前值,watch第一个参数直接写成数据源,可以不加deep:true选项 若要获取当前值和先前值,需要把数据源写成getter函数的形式,并且需对数据源进行深拷贝

🎉🎉🎉🎉🎉



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有