p"/> p">

Heim  >  Artikel  >  Web-Frontend  >  So verwenden Sie watch, um den Eigenschaftswert eines Objekts in Vue3 zu überwachen

So verwenden Sie watch, um den Eigenschaftswert eines Objekts in Vue3 zu überwachen

WBOY
WBOYnach vorne
2023-06-03 13:09:345114Durchsuche

Vue3 verwendet watch, um bestimmte Eigenschaften im Objekt abzuhören Funktion wird nur ausgeführt, wenn eine Änderung vorliegt

Der erste Parameter: Abhörquelle Die Abhörquelle kann einer der folgenden Typen sein

Eine Funktion, die einen Wert, eine Referenz, ein reaktives Objekt (reaktiv) zurückgibt oder aus dem besteht Die oben genannten Wertetypen Array

Der zweite Parameter: die Rückruffunktion, die ausgelöst werden soll, wenn sich die Abhörquelle ändert. (newValue, oldValue) => { /* code */}

Beim Abhören mehrerer Quellen akzeptiert die Rückruffunktion zwei Arrays, die dem neuen Wert und dem alten Wert im Quellarray entsprechen

( [ newValue1 , newValue2 ] , [ oldValue1 , oldValue2 ]) => {/* code */}Der dritte Parameter: optionales Objekt, das diese Optionen unterstützen kannimmediate: Der Rückruf wird sofort ausgelöst, wenn der Listener tief erstellt wird: if Die Quelle ist ein Objekt, das die Tiefendurchquerung dazu zwingt, die Rückruffunktion auszulösen, wenn sich die Tiefenebene bündig ändert: Passen Sie den Aktualisierungszeitpunkt der Rückruffunktion an onTrack / onTrigger: Debuggen Sie Listener-Abhängigkeiten

2 Grund

Weil watch Die Abhörquelle von code> kann nur die 4 oben genannten Situationen sein -Abhörquelle, cb-Rückruffunktion, options-Abhörkonfiguration und schließlich ein doWatch

4.doWatch-Quellcode werden zurückgegeben Analyse

<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>

doWatch akzeptiert weiterhin drei Parameter: source Abhörquelle, cb Rückruffunktion, options Listening-Konfiguration

Hier konzentrieren wir uns auf die Analyse des Quellcodes der Hörquelle (

Quellenstandardisierung

)

Wenn source ist ref-Typ, getter ist eine Funktion, die source.value zurückgibt, forceTrigger hängt davon ab, ob source ist flache Reaktionsfähigkeit.

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}`)
  }
)

  • watch的侦听源只能是上面的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)
    }

    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
    }

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

    4.doWatch源码分析

    if (isRef(source)) {
      getter = () => source.value
      forceTrigger = isShallow(source)
    }

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

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

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

    if (isReactive(source)) {
      getter = () => source
      deep = true
    }
    • 如果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>

    例子

    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)
          }
        })
    }
    • 如果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]
          )
        }
      }
    }
    • 如果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)
    • 其他情况getterWenn source vom Typ reactive ist, ist es auch getter eine Rückgabefunktion von source und setzen Sie deep auf true. Beim direkten Abhören eines reaktiven Objekts aktiviert der Listener automatisch den Deep-Modus

    rrreee🎜Beispiel🎜rrreee
    • 🎜wenn source ein Array ist , setzen Sie isMultiSource auf true, forceTrigger hängt davon ab, ob source reactive für Code hat > Typdaten durchläuft die Getter-Funktion die Quelle und führt unterschiedliche Verarbeitungen für verschiedene Arten von Quelle durch. 🎜🎜🎜rrreee
      • 🎜Wenn source eine function ist. Wenn cb vorhanden ist, wird source in der Funktion getter ausgeführt, wobei source callWithErrorHandlingFunktionsausführung, Fehler, die während der Ausführung von <code>source auftreten, werden in callWithErrorHandling behandelt, wenn in cb vorhanden ist >Getter , wenn die Komponente deinstalliert wurde, direkt zurück, andernfalls cleanup bestimmen (cleanup ist in watchEffect code> (Bereinigungsfunktion registriert durch <code>onCleanup), wenn es eine cleanup gibt, führen Sie cleanup aus und führen Sie dann source aus code> und Ausführungsergebnisse zurückgeben. <code>source wird von callWithAsyncErrorHandling umschlossen. Diese Funktion behandelt Fehler, die während der Ausführung von source auftreten, was sich von callWithErrorHandling Ja, <code>callWithAsyncErrorHandling behandelt asynchrone Fehler. 🎜🎜🎜rrreee
        • 🎜In anderen Fällen wird getter eine leere Funktion zugewiesen🎜🎜🎜rrreee

Das obige ist der detaillierte Inhalt vonSo verwenden Sie watch, um den Eigenschaftswert eines Objekts in Vue3 zu überwachen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:yisu.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen