В Vue вычисляемые свойства (computed properties) представляют собой механизм реактивного пересчёта значений на основе зависимостей. Их ключевая особенность заключается в кэшировании результата до тех пор, пока не изменится хотя бы одна реактивная зависимость внутри функции вычисления.
В отличие от методов, computed-свойства пересчитываются только при необходимости, что делает их предпочтительным инструментом для производных данных.
Каждое вычисляемое свойство в Vue представляет собой функцию, результат которой автоматически кэшируется системой реактивности.
export default {
data() {
return {
firstName: 'Иван',
lastName: 'Петров'
}
},
computed: {
fullName() {
return `${this.firstName} ${this.lastName}`
}
}
}
В данном примере fullName зависит от
firstName и lastName. Пока эти значения не
изменяются, повторные обращения к fullName не приводят к
повторному выполнению функции.
Методы выполняются при каждом вызове, независимо от изменений зависимостей. Computed выполняется только при изменении реактивных данных.
methods: {
getFullName() {
return `${this.firstName} ${this.lastName}`
}
}
Каждый рендер компонента вызовет getFullName() заново,
даже если данные не изменились.
Vue автоматически отслеживает зависимости внутри computed-функции. Это происходит на этапе выполнения геттеров реактивных свойств.
computed: {
totalPrice() {
return this.items.reduce((sum, item) => sum + item.price, 0)
}
}
Здесь totalPrice зависит от items. Если
изменится содержимое массива, Vue пометит computed как “грязное” и
пересчитает его при следующем обращении.
Computed свойства вычисляются лениво: только тогда, когда к ним обращаются.
computed: {
expensiveCalculation() {
return heavyComputation(this.data)
}
}
Если expensiveCalculation не используется в шаблоне или
коде, функция не будет выполняться вообще.
Кэширование является ключевым механизмом оптимизации.
При первом доступе:
При последующих обращениях:
Пока зависимости не изменились, пересчёт не происходит.
Computed свойства могут быть как только для чтения, так и с возможностью записи через setter.
computed: {
fullName: {
get() {
return `${this.firstName} ${this.lastName}`
},
set(value) {
const parts = value.split(' ')
this.firstName = parts[0]
this.lastName = parts[1] || ''
}
}
}
Теперь изменение fullName автоматически разложит строку
на отдельные поля.
Частый сценарий — производные списки.
data() {
return {
users: [
{ name: 'Anna', active: true },
{ name: 'Oleg', active: false }
],
showActive: true
}
},
computed: {
filteredUsers() {
return this.users.filter(user => {
return this.showActive ? user.active : true
})
}
}
При изменении users или showActive список
пересчитывается автоматически.
Computed может опираться на другие computed свойства, формируя цепочку реактивных вычислений.
computed: {
subtotal() {
return this.items.reduce((s, i) => s + i.price, 0)
},
tax() {
return this.subtotal * 0.2
},
total() {
return this.subtotal + this.tax
}
}
Vue корректно отслеживает всю цепочку зависимостей.
Чрезмерное использование computed может привести к:
Особенно проблемны случаи, когда computed выполняет побочные эффекты или сложные асинхронные операции, что нарушает концепцию чистой функции.
Computed свойства не предназначены для асинхронных операций.
computed: {
async data() {
const res = await fetch('/api/data')
return await res.json()
}
}
Подобный подход некорректен, поскольку computed должен возвращать синхронное значение. Для асинхронности используются методы жизненного цикла или внешние сторы состояния.
В Composition API computed реализуется через функцию
computed, возвращающую ref.
import { computed, ref } from 'vue'
const price = ref(100)
const count = ref(2)
const total = computed(() => price.value * count.value)
Значение total.value автоматически обновляется при
изменении зависимостей.
import { computed, ref } from 'vue'
const firstName = ref('Иван')
const lastName = ref('Петров')
const fullName = computed({
get: () => `${firstName.value} ${lastName.value}`,
set: (value) => {
const parts = value.split(' ')
firstName.value = parts[0]
lastName.value = parts[1] || ''
}
})
Запись в fullName.value приводит к обновлению базовых
реактивных значений.
Computed используется как инструмент снижения вычислительной нагрузки.
Типичные оптимизации:
Computed возвращает значение и используется в шаблоне или логике.
Watch используется для наблюдения за изменениями и выполнения побочных эффектов.
watch: {
firstName(newVal) {
console.log('Имя изменилось:', newVal)
}
}
Computed не предназначен для side effects, watch — предназначен.
Vue строит граф зависимостей:
Этот механизм позволяет минимизировать количество вычислений даже в больших приложениях.
Рациональная структура:
Пример хорошей структуры:
computed: {
isAdult() {
return this.age >= 18
},
status() {
return this.isAdult ? 'adult' : 'minor'
}
}
Частые ошибки включают:
Computed должен оставаться чистым вычислителем состояния.
В шаблоне computed используется как обычное свойство:
<div>{{ fullName }}</div>
<div>{{ total }}</div>
При этом Vue не вызывает функцию напрямую при каждом рендере, а использует кэшированное значение до изменения зависимостей.