Как работают вычисляемые свойства и наблюдатели в Vue.js
Система реактивности Vue автоматически отслеживает зависимости и обновляет пользовательский интерфейс при изменении данных. Но понимание того, когда использовать вычисляемые свойства Vue 3 вместо наблюдателей Vue 3, может стать разницей между чистым, производительным кодом и кошмаром сопровождения. Давайте разберём, как работают эти возможности и когда каждая из них наиболее эффективна.
Ключевые выводы
- Вычисляемые свойства — это кешируемые декларативные функции, которые создают новые значения из реактивных данных
- Наблюдатели обрабатывают побочные эффекты, такие как вызовы API, и идеально подходят для асинхронных операций
- Используйте computed для чистых преобразований, watchers — для императивной логики с побочными эффектами
- Вычисляемые свойства пересчитываются только при изменении зависимостей, что повышает производительность
Основы системы реактивности Vue
Система реактивности Vue 3 использует Proxy для отслеживания обращений к свойствам и их изменений. Когда реактивные данные изменяются, Vue точно знает, какие части вашего приложения зависят от этих данных, и эффективно их обновляет. Вычисляемые свойства и наблюдатели — два мощных инструмента, построенных на этой основе, каждый из которых служит определённым целям в вашем реактивном рабочем процессе.
Вычисляемые свойства Vue 3: декларативные и кешируемые
Вычисляемые свойства создают новые реактивные значения на основе существующих данных. Они декларативны, кешируются и всегда должны быть чистыми функциями без побочных эффектов.
Синтаксис Composition API
<script setup>
import { ref, computed } from 'vue'
const price = ref(100)
const quantity = ref(2)
const total = computed(() => price.value * quantity.value)
const formattedTotal = computed(() => `$${total.value.toFixed(2)}`)
</script>
<template>
<p>Total: {{ formattedTotal }}</p>
</template>
Синтаксис Options API
export default {
data() {
return {
price: 100,
quantity: 2
}
},
computed: {
total() {
return this.price * this.quantity
},
formattedTotal() {
return `$${this.total.toFixed(2)}`
}
}
}
Ключевое преимущество? Кеширование. Vue пересчитывает вычисляемое свойство только при изменении его зависимостей. Если вы обращаетесь к formattedTotal несколько раз в шаблоне, вычисление выполняется один раз за цикл обновления, а не при каждом обращении.
Записываемые вычисляемые свойства
Иногда вам нужно вычисляемое свойство с геттером и сеттером:
import { ref, computed } from 'vue'
const firstName = ref('John')
const lastName = ref('Doe')
const fullName = computed({
get() {
return `${firstName.value} ${lastName.value}`
},
set(newValue) {
[firstName.value, lastName.value] = newValue.split(' ')
}
})
Discover how at OpenReplay.com.
Наблюдатели Vue 3: императивные побочные эффекты
Наблюдатели отслеживают реактивные значения и выполняют побочные эффекты при их изменении. В отличие от вычисляемых свойств, наблюдатели являются императивными и идеально подходят для асинхронных операций, вызовов API или манипуляций с DOM.
Базовый синтаксис watch
// Composition API
import { ref, watch } from 'vue'
const searchQuery = ref('')
const results = ref([])
watch(searchQuery, async (newQuery) => {
if (newQuery.length > 2) {
results.value = await fetchSearchResults(newQuery)
}
})
watchEffect для автоматического отслеживания
watchEffect автоматически отслеживает зависимости без их явного объявления:
import { ref, watchEffect } from 'vue'
const searchQuery = ref('')
const results = ref([])
watchEffect(async () => {
// Автоматически отслеживает searchQuery.value
if (searchQuery.value.length > 2) {
results.value = await fetchSearchResults(searchQuery.value)
}
})
Расширенные опции наблюдателей
watch(source, callback, {
immediate: true, // Запустить немедленно при создании
deep: true, // Отслеживать вложенные свойства
flush: 'post' // Запустить после обновления DOM
})
Computed vs Watch: правильный выбор
Вот когда использовать каждый подход:
Используйте вычисляемые свойства когда:
- Создаёте новые значения на основе существующих реактивных данных
- Результат нужен в шаблоне
- Операция синхронная и чистая
- Требуется автоматическое кеширование
Используйте наблюдатели когда:
- Выполняете побочные эффекты (вызовы API, логирование, localStorage)
- Реагируете на изменения данных императивной логикой
- Обрабатываете асинхронные операции
- Нужен доступ к старому и новому значениям
Практическое сравнение
// ❌ Неправильно: побочный эффект в computed
const searchResults = computed(async () => {
const response = await fetch(`/api/search?q=${query.value}`)
return response.json() // Не сработает - computed должен быть синхронным
})
// ✅ Правильно: наблюдатель для побочных эффектов
watch(query, async (newQuery) => {
const response = await fetch(`/api/search?q=${newQuery}`)
searchResults.value = await response.json()
})
// ✅ Правильно: computed для чистого преобразования
const filteredResults = computed(() =>
searchResults.value.filter(item => item.active)
)
Соображения производительности
Вычисляемые свойства превосходны в производительности благодаря кешированию. Они пересчитываются только при изменении зависимостей, что делает их идеальными для ресурсоёмких операций:
// Пересчитывается только при изменении items или filterText
const expensiveFilter = computed(() => {
console.log('Filtering...') // Выполняется только при изменении зависимостей
return items.value.filter(item =>
complexFilterLogic(item, filterText.value)
)
})
Наблюдатели же всегда выполняются при срабатывании. Используйте их разумно, особенно с deep: true на больших объектах.
Заключение
Вычисляемые свойства Vue 3 и наблюдатели остаются фундаментальными для системы реактивности Vue. Запомните простое правило: используйте computed для чистых кешируемых преобразований, а watchers — для побочных эффектов. Вычисляемые свойства сохраняют ваши шаблоны чистыми и производительными благодаря автоматическому кешированию, в то время как наблюдатели обрабатывают императивные асинхронные операции, которые вычисляемые свойства не могут выполнить. Освойте оба инструмента, и вы будете писать приложения Vue, которые одновременно элегантны и эффективны.
Часто задаваемые вопросы
Нет, вычисляемые свойства должны быть синхронными и возвращать значения немедленно. Для асинхронных операций используйте наблюдатели или методы. Вычисляемые свойства предназначены для чистых преобразований реактивных данных.
Используйте watchEffect, когда нужно автоматическое отслеживание зависимостей и не требуется старое значение. Используйте watch, когда нужен явный контроль над тем, что отслеживать, доступ к старым значениям или специфические опции конфигурации, такие как глубокое отслеживание.
Да, вычисляемые свойства отслеживают изменения массивов и объектов. Однако для глубокой реактивности с вложенными свойствами убедитесь, что исходные данные правильно сделаны реактивными с помощью ref или reactive. Vue 3 справляется с этим лучше, чем Vue 2.
Вычисляемое свойство вычисляется только один раз за цикл рендеринга, независимо от того, сколько раз на него ссылаются. Это поведение кеширования делает вычисляемые свойства эффективными для ресурсоёмких вычислений, используемых в нескольких местах.
Gain Debugging Superpowers
Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers. Check our GitHub repo and join the thousands of developers in our community.