# Вычисляемые свойства и методы-наблюдатели

В этом разделе в примерах кода используется синтаксис однофайловых компонентов

# computed

Принимает геттер-функцию и возвращает иммутабельный реактивный ref-объект для возвращаемого значения из геттера.

const count = ref(1)
const plusOne = computed(() => count.value + 1)

console.log(plusOne.value) // 2

plusOne.value++ // ошибка
1
2
3
4
5
6

Может быть объект с функциями get и set для создания ref-объекта для чтения/записи.

const count = ref(1)
const plusOne = computed({
  get: () => count.value + 1,
  set: val => {
    count.value = val - 1
  }
})

plusOne.value = 1
console.log(count.value) // 0
1
2
3
4
5
6
7
8
9
10

Типизация:

// только для чтения
function computed<T>(getter: () => T): Readonly<Ref<Readonly<T>>>

// чтение/запись
function computed<T>(options: { get: () => T; set: (value: T) => void }): Ref<T>
1
2
3
4
5

# watchEffect

Немедленно запускает функцию, отслеживая её зависимости с помощью системы реактивности, а затем повторно вызывает лишь при изменении этих зависимостей.

const count = ref(0)

watchEffect(() => console.log(count.value))
// -> выведет 0

setTimeout(() => {
  count.value++
  // -> выведет 1
}, 100)
1
2
3
4
5
6
7
8
9

Типизация:

function watchEffect(
  effect: (onInvalidate: InvalidateCbRegistrator) => void,
  options?: WatchEffectOptions
): StopHandle

interface WatchEffectOptions {
  flush?: 'pre' | 'post' | 'sync'
  onTrack?: (event: DebuggerEvent) => void
  onTrigger?: (event: DebuggerEvent) => void
}

interface DebuggerEvent {
  effect: ReactiveEffect
  target: any
  type: OperationTypes
  key: string | symbol | undefined
}

type InvalidateCbRegistrator = (invalidate: () => void) => void

type StopHandle = () => void
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

См. также: Руководство по watchEffect

# watch

API watch является точным эквивалентом this.$watch Options API (и соответствующей опции watch). Для watch требуется отслеживание конкретного источника данных и применяет побочные эффекты в отдельном коллбэке. По умолчанию она также является «ленивой» — коллбэк вызывается только тогда, когда наблюдаемый источник изменился.

  • В сравнении с watchEffect, watch позволяет:

    • Выполнять побочный эффект лениво;
    • Конкретнее определять какое состояние должно вызывать повторный запуск метода-наблюдателя;
    • Предоставляет доступ к предыдущему и текущему значениям отслеживаемого состояния.

# Отслеживание единственного источника данных

Источником данных для наблюдателя может быть функция геттер, возвращающая значение, или непосредственно реактивная ref-ссылка:

// наблюдение за геттер-функцией
const state = reactive({ count: 0 })
watch(
  () => state.count,
  (count, prevCount) => {
    /* ... */
  }
)

// наблюдение за ref-ссылкой
const count = ref(0)
watch(count, (count, prevCount) => {
  /* ... */
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# Отслеживание нескольких источников данных

Можно отслеживать несколько источников одновременно, используя массив при записи:

watch([fooRef, barRef], ([foo, bar], [prevFoo, prevBar]) => {
  /* ... */
})
1
2
3

# Общее поведение с watchEffect

Общее поведение watch и watchEffect будет в возможностях остановки отслеживания, аннулировании побочных эффектов (с передачей коллбэка onInvalidate третьим аргументом), синхронизации времени очистки эффектов и инструментов отладки.

Типизация:

// отслеживание единственного источника данных
function watch<T>(
  source: WatcherSource<T>,
  callback: (
    value: T,
    oldValue: T,
    onInvalidate: InvalidateCbRegistrator
  ) => void,
  options?: WatchOptions
): StopHandle

// отслеживание нескольких источников данных
function watch<T extends WatcherSource<unknown>[]>(
  sources: T
  callback: (
    values: MapSources<T>,
    oldValues: MapSources<T>,
    onInvalidate: InvalidateCbRegistrator
  ) => void,
  options? : WatchOptions
): StopHandle

type WatcherSource<T> = Ref<T> | (() => T)

type MapSources<T> = {
  [K in keyof T]: T[K] extends WatcherSource<infer V> ? V : never
}

// обратитесь к типам `watchEffect` для общих опций
interface WatchOptions extends WatchEffectOptions {
  immediate?: boolean // по умолчанию: false
  deep?: boolean
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

См. также: Руководство по watch