Skip to content
Topic 4 of 5
Theory

computed и watch

Вычисляемые значения

Часто на экране нужно не само состояние, а что-то, посчитанное из него: полное имя из имени и фамилии, сумма корзины, отфильтрованный список, «можно ли отправить форму». Писать это выражение прямо в шаблоне неудобно, а хранить в отдельном ref и обновлять вручную — источник ошибок.

Для этого во Vue есть computed:

const { ref, computed } = Vue;

const price = ref(100);
const qty = ref(3);
const total = computed(() => price.value * qty.value);

console.log(total.value);   // 300
qty.value = 5;
console.log(total.value);   // 500 — пересчиталось само

computed получает функцию-«формулу». Vue запоминает, от каких реактивных данных она зависит (price и qty), и пересчитывает результат, только когда они меняются. В шаблоне — без .value: {{ total }}.

computed или функция?

В прошлой теме мы вызывали в шаблоне функции: {{ price() }}. Разница в кэше:

  • функция выполняется при каждой перерисовке компонента;
  • computed хранит результат и пересчитывает его, только если изменились зависимости.

Для дешёвых выражений разницы почти нет, а для фильтрации больших списков, сортировки, сложных подсчётов computed заметно экономнее. Поэтому производные данные во Vue принято делать через computed.

const todos = ref([...]);
const filter = ref("all");

const visible = computed(() => {
  if (filter.value === "done") return todos.value.filter((t) => t.done);
  if (filter.value === "active") return todos.value.filter((t) => !t.done);
  return todos.value;
});
const left = computed(() => todos.value.filter((t) => !t.done).length);

Функция внутри computed должна только считать и возвращать: не менять другие данные, не делать запросов. Для действий есть watch.

watch — следить за изменениями

watch вызывает функцию, когда меняется источник. Это место для побочных эффектов: сохранить в localStorage, отправить запрос, записать в журнал.

const { ref, watch } = Vue;

const theme = ref(localStorage.getItem("theme") ?? "light");

watch(theme, (newValue, oldValue) => {
  localStorage.setItem("theme", newValue);
  console.log(`Тема: ${oldValue} → ${newValue}`);
});

Источник — ref, computed, реактивный объект или функция-геттер: watch(() => user.age, (age) => ...).

Полезные настройки:

watch(query, search, { immediate: true });   // вызвать сразу, не дожидаясь изменения
watch(settings, save, { deep: true });        // следить за вложенными полями объекта

computed vs watch

Нужно Используй
значение, посчитанное из других данных computed
сделать что-то, когда данные изменились watch

Если ловишь себя на коде «в watch записываю результат в другой ref» — почти наверняка это должен быть computed.

Итог

  • computed(() => формула) — производное значение с кэшем; в шаблоне без .value.
  • Внутри computed только считаем, без побочных эффектов.
  • watch(источник, (новое, старое) => ...) — реакция на изменение: сохранение, запросы, журнал.
  • Опции watch: immediate, deep.

Полное имя

Easy+10 XP

В компоненте FullName есть два ref: first и last. Создай computed с именем full: имя и фамилия через пробел, без лишних пробелов, если одно из них пустое. Покажи его в <p>{{ full }}</p> и верни из setup.

"Ada", "Lovelace"  →  Ada Lovelace
"Ada", ""          →  Ada

Connect the connector to solve tasks

Task code runs on your own computer — faster and more reliable than in the browser. This needs the free CodeWithMe connector app. You only connect it once.

Looking for the connector on this computer…

  1. 1
    Download the connector for your system (Windows, macOS or Linux).Download the connectorOn the download page pick the file with your system in its name, e.g. windows-amd64.
  2. 2Run it and choose a folder for your solutions. It will install Python and Node.js there by itself when needed.
  3. 3
    Enter below the 6-digit code shown in the connector window (“Code for CodeWithMe”). If the browser asks about local network access — allow it.

The connector is open source (on GitHub), works only on your computer and runs code only after you enter the pairing code.