Что такое computed-свойства и как они отличаются от методов?

В Vue.js computed-свойства (вычисляемые свойства) представляют собой способ определения значений, которые вычисляются на основе других реактивных данных и кэшируются для повышения производительности. Они позволяют описывать зависимые значения, которые автоматически пересчитываются только тогда, когда изменяются данные, от которых они зависят. Это делает computed-свойства удобным инструментом для создания производительных и читаемых интерфейсов.

Основная идея computed-свойств

В отличие от обычных методов или прямого обращения к переменным, computed-свойства автоматически отслеживают свои зависимости и повторно вычисляются только тогда, когда какая-либо из зависимостей изменилась. Это обеспечивает высокую производительность при обновлении DOM.

Пример computed-свойства

export default {
data() {
return {
firstName: 'Иван',
lastName: 'Иванов'
}
},
computed: {
fullName() {
return this.firstName + ' ' + this.lastName;
}
}
}

Здесь fullName зависит от firstName и lastName. Vue автоматически отслеживает эти зависимости. Когда одно из значений меняется — Vue пересчитывает fullName, но только тогда, когда оно реально требуется (например, при отображении на странице). Если firstName и lastName не изменяются, повторного вычисления не происходит.

Как computed отличается от методов

1. Кэширование

Computed-свойства кэшируются, а методы — нет.

Если computed-свойство вызывается несколько раз в шаблоне, Vue не будет повторно вызывать функцию, пока её зависимости не изменятся. Это особенно важно, если вычисление ресурсоёмкое.

Методы выполняются в каждый ререндер компонента, независимо от того, изменились ли данные.

Пример:

<!-- Вызывает метод каждый раз -->
<p>{{ someMethod() }}</p>
<p>{{ someMethod() }}</p>
<!-- Вычисляется один раз и кэшируется -->
<p>{{ someComputed }}</p>
<p>{{ someComputed }}</p>

2. Использование в шаблоне

Обычно computed-свойства используются как свойства:

<p>{{ fullName }}</p>

А методы используются как функции:

<p>{{ getFullName() }}</p>

3. Цель использования

  • Computed подходит для производных значений на основе других данных (например, фильтрация, объединение строк, подсчёты).

  • Methods — для вызова действий (например, обработка кликов, асинхронные операции) или не зависящих от реактивных данных.

Внутреннее устройство computed-свойств

Когда Vue инициализирует компонент, он создает объект computed, в котором каждая функция (например, fullName) оборачивается во внутренний геттер, отслеживающий зависимости.

Если в ходе выполнения fullName() Vue "видит", что ты используешь this.firstName и this.lastName, то он подписывается на их изменения. Как только одна из зависимостей изменится — computed-поле будет помечено как "грязное", и при следующем обращении к нему оно пересчитается.

Пример с кэшированием

data() {
return {
a: 1,
b: 2
}
},
computed: {
sum() {
console.log('computing sum');
return this.a + this.b;
}
}
<!-- sum будет вычислена только один раз -->
<p>{{ sum }}</p>
<p>{{ sum }}</p>

В консоли computing sum появится только один раз, пока a или b не изменятся. Если бы это был метод, консоль лог был бы дважды.

computed с геттером и сеттером

В некоторых случаях нужно не только вычислять значение, но и изменять его.

computed: {
fullName: {
get() {
return this.firstName + ' ' + this.lastName;
},
set(newValue) {
const parts = newValue.split(' ');
this.firstName = parts\[0\];
this.lastName = parts\[1\];
}
}
}

Теперь v-model может использовать это computed-свойство:

<input v-model="fullName">

Ввод в это поле будет автоматически обновлять firstName и lastName.

Ограничения и тонкости

  • Computed-свойства должны быть синхронными. Нельзя использовать async/await или возвращать промис.

  • Для асинхронных вычислений лучше использовать watcher или методы.

  • Не стоит путать computed с watch. watch используется для реакции на изменения, а computed — для получения нового значения.

Когда использовать computed, а когда методы

Используй computed, если:

  • Нужно производное значение от других реактивных данных.

  • Это значение зависит от других полей data.

  • Оно должно быть кэшировано между рендерами.

  • Ты планируешь обращаться к нему часто в шаблоне.

Используй методы, если:

  • Результат не зависит от реактивных данных.

  • Каждый вызов должен быть независимым.

  • Логика требует выполнения кода при каждом обращении.

  • Это асинхронная операция.

Computed-свойства — это мощный инструмент в Vue, позволяющий эффективно строить производные состояния и автоматически синхронизировать их с UI без дублирования логики и избыточных вычислений.