watch를 사용하여 Vue3에서 객체의 속성 값을 모니터링하는 방법

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 listening이며, 이는 listening 소스에서만 발생합니다. 함수는 변경이 있을 때만 실행됩니다

첫 번째 매개변수: 청취 소스는 다음 유형 중 하나일 수 있습니다.

값, ref, 반응형 객체(reactive)를 반환하거나 다음으로 구성되는 함수입니다. 위 유형의 값 배열

두 번째 매개변수: 청취 소스가 변경될 때 트리거되는 콜백 함수입니다.

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

여러 소스를 수신할 때 콜백 함수는 소스 배열의 새 값과 이전 값에 해당하는 두 개의 배열을 허용합니다.

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

세 번째 매개변수: 이러한 옵션을 지원할 수 있는 선택적 개체

immediate: 리스너가 깊게 생성되면 콜백이 즉시 트리거됩니다. 소스는 딥 레벨이 플러시로 변경될 때 콜백 함수를 트리거하도록 깊이 탐색을 강제하는 객체입니다. 콜백 함수의 새로 고침 타이밍을 조정합니다. onTrack / onTrigger: 디버그 리스너 종속성

2 이유

보기 </ code>의 청취 소스는 위의 4가지 상황만 가능합니다<code>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.watch源码分析

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接收三个参数:source侦听源、cb回调函数、options侦听配置,最后会返回一个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依然接受三个参数:source侦听源、cb回调函数、options侦听配置

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

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

if (isRef(source)) {
  getter = () => source.value
  forceTrigger = isShallow(source)
}
로그인 후 복사
  • 如果sourcereactive类型,getter是个返回source的函数,并将deep设置为true。 当直接侦听一个响应式对象时,侦听器会自动启用深层模式

if (isReactive(source)) {
  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>
로그인 후 복사
  • 如果source是个数组,将isMultiSource设为trueforceTrigger取决于source是否有reactive类型的数据,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)
      }
    })
}
로그인 후 복사
  • 如果source是个function。存在cb的情况下,getter函数中会执行source,这里source会通过callWithErrorHandling函数执行,在callWithErrorHandling中会处理source执行过程中出现的错误;不存在cb的话,在getter中,如果组件已经被卸载了,直接return,否则判断cleanupcleanup是在watchEffect中通过onCleanup注册的清理函数),如果存在cleanup执行cleanup,接着执行source,并返回执行结果。source会被callWithAsyncErrorHandling包装,该函数作用会处理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)
    로그인 후 복사
    3.watch 소스 코드 분석rrreeewatch가 세 가지 매개변수 소스를 받는 것을 소스 코드에서 볼 수 있습니다. 청취 소스, cb 콜백 함수, options 청취 구성, 그리고 마지막으로 doWatch🎜🎜4.doWatch 소스 코드가 반환됩니다. 분석 🎜rrreee🎜doWatch는 여전히 source 청취 소스, cb 콜백 함수, options 청취 청취 구성의 세 가지 매개변수를 허용합니다. 🎜🎜여기에서는 청취 소스의 소스 코드 분석에 중점을 둡니다(🎜소스 표준화🎜)🎜
    • 🎜source인 경우 ref 유형, gettersource.value를 반환하는 함수입니다. forceTriggersource 여부에 따라 다릅니다. 얕은 반응성입니다. 🎜🎜🎜rrreee
      • 🎜 sourcereactive 유형인 경우 gettersource의 반환 함수를 사용하고 deeptrue로 설정하세요. 반응형 객체를 직접 들을 때 리스너는 자동으로 딥 모드를 활성화합니다 🎜🎜🎜rrreee🎜Example🎜rrreee
        • 🎜 source가 배열인 경우 , isMultiSourcetrue로 설정하세요. forceTriggersourcereactive가 있는지 여부에 따라 달라집니다. > 유형 데이터인 경우 getter 함수는 source를 순회하고 다양한 유형의 source에 대해 서로 다른 처리를 수행합니다. 🎜🎜🎜rrreee
          • 🎜 source함수인 경우. cb가 존재하는 경우 sourcegetter 함수에서 실행되며, 여기서 sourcecallWithErrorHandling함수 실행, <code>source 실행 중 발생하는 오류는 cb가 없으면 callWithErrorHandling에서 처리됩니다. >getter , 구성 요소가 제거된 경우 직접 return하고, 그렇지 않으면 cleanup을 결정합니다(cleanupwatchEffect code> (<code>onCleanup을 통해 등록된 정리 함수), cleanup이 있으면 cleanup을 실행한 후 source를 실행합니다. code> 및 실행 결과를 반환합니다. <code>sourcecallWithAsyncErrorHandling으로 래핑됩니다. 이 함수는 callWithErrorHandlingsource 실행 중에 발생하는 오류를 처리합니다. /code> 예, callWithAsyncErrorHandling은 비동기 오류를 처리합니다. 🎜🎜🎜rrreee
            • 🎜다른 경우에는 getter에 빈 함수가 할당됩니다🎜🎜🎜rrreee

    위 내용은 watch를 사용하여 Vue3에서 객체의 속성 값을 모니터링하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:yisu.com
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿
회사 소개 부인 성명 Sitemap
PHP 중국어 웹사이트:공공복지 온라인 PHP 교육,PHP 학습자의 빠른 성장을 도와주세요!