Maison > interface Web > Voir.js > Comment utiliser watch pour surveiller la valeur de propriété d'un objet dans Vue3

Comment utiliser watch pour surveiller la valeur de propriété d'un objet dans Vue3

WBOY
Libérer: 2023-06-03 13:09:34
avant
5245 Les gens l'ont consulté

Utilisez watch dans Vue3 pour écouter des propriétés spécifiques dans les objets

1 Préface

<script lang="ts" setup>
	// 接受父组件传递的数据
    const props = defineProps({
        test: {
            type: String,
            default: &#39;&#39;
        }
    })
    
    // 使用 watch 侦听 props 中的 test 属性
    watch(
        // 这种写法不会侦听到 props 中 test 的变化
    	props.test,
        () => {
            console.log("侦听成功")
        }
    )
    
    watch(
    	// 这种写法会侦听到 props 中 test 的变化
        () => props.test,
        () => {
            console.log("侦听成功")
        }
    )
</script>
Copier après la connexion

Utilisation de base de watch#🎜🎜 #

watch() est par défaut

écoute paresseuse, c'est-à-dire que la fonction de rappel n'est exécutée que lorsque la source d'écoute change#🎜 🎜 #Le premier paramètre : source d'écoute, la source d'écoute peut être l'un des types suivants

Une fonction qui renvoie une valeur, une référence, un objet réactif (réactif) ou se compose des types de valeurs ci-dessus Tableau de

Le deuxième paramètre : la fonction de rappel à déclencher lorsque la source d'écoute change.

(newValue, oldValue) => { /* code */}

Lors de l'écoute de plusieurs sources, la fonction de rappel accepte deux tableaux, correspondant aux tableaux sources. La nouvelle valeur et l'ancienne valeur dans

( [ newValue1, newValue2 ] , [ oldValue1 , oldValue2 ]) => code */}

Le troisième paramètre : Objet facultatif, vous pouvez supporter ces options

immediate : Le rappel est déclenché immédiatement lorsque l'écouteur est créé en profondeur : Si la source est un objet, le parcours en profondeur sera forcé pour que la fonction de rappel soit déclenchée lorsque le niveau profond changes flush : Ajustement du timing d'actualisation de la fonction de rappel onTrack / onTrigger : dépendance de l'écouteur de débogage

2 Raison

Parce que la source d'écoute de watch ne peut que. be Les 4 situations ci-dessus

const obj = reactive({ count: 0 })

// 错误,因为 watch() 中的侦听源是一个 number,最终 source 返回的 getter 函数是一个空,所以就得不到侦听的数据
watch(obj.count, (count) => {
  console.log(`count is: ${count}`)
})

// 正确,主要思想是,将侦听源转化为以上4种类型(转化为getter函数是最简单方便的)
watch(
  () => obj.count,
  (count) => {
    console.log(`count is: ${count}`)
  }
)
Copier après la connexion

3.watch analyse du code sourcewatch的侦听源只能是上面的4中情况

export function watch<T = any, Immediate extends Readonly<boolean> = false>(
  source: T | WatchSource<T>,
  cb: any,
  options?: WatchOptions<Immediate>
): WatchStopHandle {
  if (__DEV__ && !isFunction(cb)) {
    warn(
      `\`watch(fn, options?)\` signature has been moved to a separate API. ` +
      `Use \`watchEffect(fn, options?)\` instead. \`watch\` now only ` +
      `supports \`watch(source, cb, options?) signature.`
    )
  }
  return doWatch(source as any, cb, options)
}
Copier après la connexion

3.watch源码分析

function doWatch(
  source: WatchSource | WatchSource[] | WatchEffect | object,
  cb: WatchCallback | null,
  { immediate, deep, flush, onTrack, onTrigger }: WatchOptions = EMPTY_OBJ
): WatchStopHandle {
  // ...
// 当前组件实例
const instance = currentInstance
// 副作用函数,在初始化effect时使用
let getter: () => any
// 强制触发侦听
let forceTrigger = false
// 是否为多数据源。
let isMultiSource = false
}
Copier après la connexion

从源码中可以看出,watch接收三个参数:source侦听源、cb回调函数、options侦听配置,最后会返回一个doWatch

4.doWatch源码分析

if (isRef(source)) {
  getter = () => source.value
  forceTrigger = isShallow(source)
}
Copier après la connexion

doWatch依然接受三个参数:source侦听源、cb回调函数、options侦听配置

这里着重对侦听源的源码进行分析(source标准化

  • 如果sourceref类型,getter是个返回source.value的函数,forceTrigger取决于source是否是浅层响应式。

if (isReactive(source)) {
  getter = () => source
  deep = true
}
Copier après la connexion
  • 如果sourcereactive类型,getter是个返回source的函数,并将deep设置为true。 当直接侦听一个响应式对象时,侦听器会自动启用深层模式

<template>
  <div class="container">
    <h3>obj---{{ obj }}</h3>
    <button @click="changeName">修改名字</button>
    <button @click="changeAge">修改年龄</button>
  </div>
</template>

<script lang="ts" setup>
import { reactive, watch } from "vue";
const obj = reactive({
  name: "张三",
  age: 18,
});
const changeName = () => {
  obj.name += "++";
};
const changeAge = () => {
  obj.age += 1;
};
// obj 中的任一属性变化了,都会被监听到
watch(obj, () => {
  console.log("变化了");
});
</script>
Copier après la connexion

例子

if (isArray(source)) {
  isMultiSource = true
  forceTrigger = source.some(isReactive)
  getter = () =>
    source.map(s => {
      if (isRef(s)) {
        return s.value
      } else if (isReactive(s)) {
        return traverse(s)
      } else if (isFunction(s)) {
        return callWithErrorHandling(s, instance, ErrorCodes.WATCH_GETTER)
      } else {
        __DEV__ && warnInvalidSource(s)
      }
    })
}
Copier après la connexion
  • 如果source是个数组,将isMultiSource设为trueforceTrigger取决于source是否有reactive类型的数据,getter函数中会遍历source,针对不同类型的source做不同处理。

if (isFunction(source)) {
  if (cb) {
    getter = () =>
      callWithErrorHandling(source, instance, ErrorCodes.WATCH_GETTER)
  } else {
    // watchEffect
    getter = () => {
      // 如果组件实例已经卸载,直接return
      if (instance && instance.isUnmounted) {
        return
      }
      // 如果清理函数,则执行清理函数
      if (cleanup) {
        cleanup()
      }
      // 执行source,传入onCleanup,用来注册清理函数
      return callWithAsyncErrorHandling(
        source,
        instance,
        ErrorCodes.WATCH_CALLBACK,
        [onCleanup]
      )
    }
  }
}
Copier après la connexion
  • 如果source是个function。存在cb的情况下,getter函数中会执行source,这里source会通过callWithErrorHandling函数执行,在callWithErrorHandling中会处理source执行过程中出现的错误;不存在cb的话,在getter中,如果组件已经被卸载了,直接return,否则判断cleanupcleanup是在watchEffect中通过onCleanup注册的清理函数),如果存在cleanup执行cleanup,接着执行source,并返回执行结果。source会被callWithAsyncErrorHandling包装,该函数作用会处理source执行过程中出现的错误,与callWithErrorHandling不同的是,callWithAsyncErrorHandling会处理异步错误。

getter = NOOP
__DEV__ && warnInvalidSource(source)
Copier après la connexion
  • 其他情况getterrrreee

    Comme le montre le code source, watch reçoit trois paramètres : source source d'écoute, fonction de rappel cb, configuration d'écoute options, et enfin un doWatch
  • # être renvoyé 🎜🎜#4.doWatch analyse du code source
rrreee#🎜🎜#doWatch accepte toujours trois paramètres : source source d'écoute, cb code >Fonction de rappel, <code>optionsConfiguration de l'écoute#🎜🎜##🎜🎜#Ici on se concentre sur l'analyse du code source de la source d'écoute (#🎜🎜#standardisation de la source#🎜🎜#)#🎜🎜 #
  • #🎜🎜#Si source est de type ref, getter est un retour de la fonction de Source.value, forceTrigger dépend du fait que source soit peu réactif. #🎜🎜##🎜🎜##🎜🎜#rrreee
    • #🎜🎜#Si source est réactif Tapez, getter est une fonction qui renvoie source et définit deep sur true. Lors de l'écoute directe d'un objet réactif, l'écouteur active automatiquement le mode profond 2">
    • #🎜🎜#Si source est un tableau, définissez isMultiSource sur true, forceTrigger Selon que source possède ou non des données de type réactif, la fonction getter parcourra source pour différents types de source est traité différemment. #🎜🎜##🎜🎜##🎜🎜#rrreee
      • #🎜🎜#Si source est une fonction . Lorsque cb existe, source sera exécuté dans la fonction getter, où source passera callWithErrorHandlingExécution de la fonction, les erreurs qui surviennent lors de l'exécution de <code>source seront gérées dans callWithErrorHandling s'il n'y a pas de cb, dans getter , si le composant a été désinstallé, directement return, sinon déterminez cleanup (cleanup est dans watchEffect code> (fonction de nettoyage enregistrée via <code>onCleanup), s'il y a cleanup, exécutez cleanup, puis exécutez source code> et renvoyer les résultats de l'exécution. <code>source sera enveloppé par callWithAsyncErrorHandling. Cette fonction gérera les erreurs qui se produisent lors de l'exécution de source, qui est différente de callWithErrorHandling<.> Oui, <code>callWithAsyncErrorHandling gérera les erreurs asynchrones. #🎜🎜##🎜🎜##🎜🎜#rrreee
        • #🎜🎜#Dans les autres cas, getter se verra attribuer une fonction vide #🎜🎜##🎜🎜##🎜🎜#rrreee
  • Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

    Étiquettes associées:
    source:yisu.com
    Déclaration de ce site Web
    Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
    Tutoriels populaires
    Plus>
    Derniers téléchargements
    Plus>
    effets Web
    Code source du site Web
    Matériel du site Web
    Modèle frontal