Vue3 で watch を使用してオブジェクトのプロパティ値を監視する方法

WBOY
リリース: 2023-06-03 13:09:34
転載
5154 人が閲覧しました

Vue3 で watch を使用してオブジェクトの特定のプロパティをリッスンする

1. はじめに

<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>
ログイン後にコピー

watch の基本的な使用法

watch () デフォルトは lazy listens です。つまり、コールバック関数は listening ソース が変更された場合にのみ実行されます

最初のパラメーター: listen ソース、listeningソースは次のタイプのいずれかになります。

値、ref、応答オブジェクト (リアクティブ)、または上記のタイプの値で構成される配列を返す関数です。

2 番目のパラメーター: リスニング ソースが変更されたときトリガーされるコールバック関数。

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

複数のソースをリッスンする場合、コールバック関数は、次の新しい値に対応する 2 つの配列を受け入れます。ソース配列と古い値

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

3 番目のパラメータ: オプションのオブジェクト。これらのオプションがサポートされます

immediate: リスナーが作成されるとすぐにコールバックをトリガーします deep: ソースがオブジェクトの場合、深いレベルが変更されたときにコールバック関数がトリガーされるように深度トラバーサルが強制されます フラッシュ: のリフレッシュ タイミングを調整しますコールバック関数 onTrack/onTrigger: デバッグ リスナーの依存関係

2. 理由

watch のリスニング ソースは上記 4 つの状況のみであるため

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}`)
  }
)
ログイン後にコピー

3. ウォッチのソース コード分析

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)
}
ログイン後にコピー

ソース コードから、watch が 3 つのパラメーターを受け取ることがわかります: sourcelistening source、cb コールバック関数、オプションリスニング構成は最終的に doWatch

4.doWatch ソース コード分析

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
}
ログイン後にコピー

doWatch#を返します##引き続き 3 つのパラメータを受け入れます: sourceListening ソース、cbCallback function、optionsListening 構成

ここでは、ソース コードの分析に焦点を当てます。リスニングソースの (

ソース標準化)

  • sourceref 型の場合、getter は returnsource.valueforceTrigger の機能は、source が浅い応答性であるかどうかによって異なります。

  • if (isRef(source)) {
      getter = () => source.value
      forceTrigger = isShallow(source)
    }
    ログイン後にコピー
  • sourcereactive タイプの場合、getter は戻り値 source 関数を実行し、deeptrue に設定します。リアクティブ オブジェクトを直接リッスンする場合、リスナーは自動的にディープ モードを有効にします

  • if (isReactive(source)) {
      getter = () => source
      deep = true
    }
    ログイン後にコピー
Example

<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

    source は配列。 isMultiSourcetrue に設定します。 forceTrigger は、sourcereactive 型であるかどうかによって異なります。 getter 関数は source を走査し、さまざまなタイプの source に対してさまざまな処理を実行します。

  • 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)
          }
        })
    }
    ログイン後にコピー
  • sourcefunction の場合。 cb が存在する場合、sourcegetter 関数で実行され、sourcecallWithErrorHandling## を通じて実行されます。 # function 、source の実行中に発生したエラーは callWithErrorHandling で処理されます; cb が存在しない場合は、getter で、コンポーネントがアンインストールされている場合は直接 return、それ以外の場合は cleanup を判断します (cleanupwatchEffect# の onCleanup を通じて登録されます) ## Cleanup 関数)、cleanup が存在する場合、cleanup を実行し、その後 source を実行して、実行結果を返します。 sourcecallWithAsyncErrorHandling によってラップされます。この関数は、source の実行中に発生するエラーを処理します。callWithErrorHandling との違いは次のとおりです。 callWithAsyncErrorHandling は非同期エラーを処理します。

    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]
          )
        }
      }
    }
    ログイン後にコピー

その他のケース
    getter
  • は空の関数に割り当てられます

    getter = NOOP
    __DEV__ && warnInvalidSource(source)
    ログイン後にコピー

    以上がVue3 で watch を使用してオブジェクトのプロパティ値を監視する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:yisu.com
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!