Вычисляемые свойства: computed

Учимся выводить значения из других значений через computed: автоматический пересчёт, кеширование и чем это лучше обычного метода.

computed — реактивное вычисляемое свойство: оно зависит от других реактивных данных, пересчитывается только когда они меняются, и кеширует результат.

Зачем нужны вычисляемые свойства

Часто значение нужно не хранить, а выводить из других: полное имя из имени и фамилии, итог корзины из списка товаров, отфильтрованный список. Можно писать такое выражение прямо в шаблоне, но он быстро становится нечитаемым. computed выносит логику и делает её реактивной:

<template>
  <p>{{ firstName }} {{ lastName }}</p>
  <p>Полное имя: {{ fullName }}</p>
</template>

<script setup>
import { ref, computed } from 'vue'

const firstName = ref('Аня')
const lastName = ref('Иванова')

const fullName = computed(() => firstName.value + ' ' + lastName.value)
</script>

Как только меняется firstName или lastName, fullName пересчитывается сам. В шаблоне computed используется как обычный ref — без .value.

Кеширование — главное отличие от метода

Можно было бы сделать метод getFullName() и вызывать его в шаблоне. Но метод выполняется при каждой перерисовке, даже если данные не менялись. computed же кеширует результат и пересчитывает его, только когда меняется зависимость. Прочувствуем разницу через счётчик вызовов:

let calls = 0;

// Имитация computed с кешем по зависимости
function makeComputed(getDep, fn) {
  let cachedDep, cachedVal;
  return () => {
    const dep = getDep();
    if (dep !== cachedDep) {       // пересчитать только если зависимость изменилась
      cachedDep = dep;
      cachedVal = fn(dep);
      calls++;
    }
    return cachedVal;
  };
}

let price = 100;
const total = makeComputed(() => price, p => p * 1.2);

console.log(total());   // считает
console.log(total());   // берёт из кеша
console.log(total());   // берёт из кеша
price = 200;
console.log(total());   // зависимость изменилась — считает заново
console.log("Реальных пересчётов:", calls);

Вывод:

120
120
120
240
Реальных пересчётов: 2

Хотя total() вызвали 4 раза, реальных вычислений было только 2 — остальное взято из кеша. Именно так экономит ресурсы computed в больших списках и тяжёлых вычислениях.

Фильтрация списка через computed

<script setup>
import { ref, computed } from 'vue'

const search = ref('')
const users = ref(['Аня', 'Борис', 'Артём', 'Вера'])

const filtered = computed(() =>
  users.value.filter(u => u.toLowerCase().includes(search.value.toLowerCase()))
)
</script>

computed против method

computedметод
Кешированиеда, по зависимостямнет, считает каждый раз
Вызов в шаблонекак свойство: {{ x }}как функция: {{ x() }}
Для чегопроизводные данныедействия по событию

Итог

  • computed создаёт производное значение из других реактивных данных.
  • Пересчитывается автоматически при изменении зависимостей.
  • Кеширует результат — в отличие от метода, который выполняется при каждой перерисовке.
  • В шаблоне используется как обычный ref, без .value.
Проверьте себя
1. Чем computed принципиально отличается от обычного метода в шаблоне?
Acomputed нельзя использовать в шаблоне
Bcomputed кеширует результат и пересчитывается только при изменении зависимостей, а метод выполняется при каждой перерисовке
CМетод работает быстрее во всех случаях
Dcomputed не может зависеть от ref
2. Когда пересчитывается вычисляемое свойство?
AКаждую секунду по таймеру
BПри каждой перерисовке компонента
CТолько когда изменяется одна из реактивных зависимостей, от которых оно зависит
DНикогда, его нужно пересчитывать вручную
3. Как использовать computed-свойство fullName в шаблоне?
A{{ fullName() }}
B{{ fullName }}
C{{ fullName.value }}
D{{ computed(fullName) }}
Поддержать проект