Когда мы разрабатываем приложения, особенно сложные, часто возникает потребность работать с производными данными. Представьте: у вас есть исходные данные, но для отображения или логики вам нужны данные, основанные на них. Вот где вычисляемые свойства и наблюдатели становятся вашими лучшими друзьями. В этой статье мы разберём, как их использовать в Vue 3 с Composition API.
Вычисляемые свойства (Computed Properties)
Начнём с того, что вычисляемые свойства в Vue позволяют вам создавать производные данные на основе других реактивных переменных. Они похожи на методы, но с ключевым отличием — Vue автоматически кэширует результаты вычисления, пока зависимости не изменятся.
Почему не использовать методы?
Многие задаются вопросом: почему бы не использовать обычные методы для обработки производных данных? Ответ в производительности. Каждый раз, когда вызывается метод, он выполняется заново, даже если данные не изменились. Вычисляемые свойства, напротив, *запоминают* результат и не пересчитываются, если нет изменений в исходных данных. Это экономит ресурсы и ускоряет работу приложения.
Пример вычисляемого свойства
Представим простую задачу: у нас есть список товаров с ценами, и нам нужно подсчитать общую стоимость. Логично было бы сделать это с помощью вычисляемого свойства.
<template>
<div>
<p>Total price: {{ totalPrice }}</p>
</div>
</template>
<script setup>
import { ref, computed } from 'vue';
const products = ref([
{ name: 'Product 1', price: 100 },
{ name: 'Product 2', price: 150 },
{ name: 'Product 3', price: 200 },
]);
const totalPrice = computed(() => {
return products.value.reduce((sum, product) => sum + product.price, 0);
});
</script>
Здесь *totalPrice* — это вычисляемое свойство, которое автоматически пересчитывает общую сумму товаров только тогда, когда изменяется массив *products*.
Двусторонняя привязка и геттеры/сеттеры
Иногда требуется не просто получать значения, но и изменять их через вычисляемые свойства. Для этого в Vue 3 можно использовать геттеры и сеттеры.
Пример с двусторонней привязкой:
<template>
<div>
<p>Discounted price: {{ discountedPrice }}</p>
<input v-model="discountedPrice" type="number" />
</div>
</template>
<script setup>
import { ref, computed } from 'vue';
const price = ref(200);
const discountedPrice = computed({
get() {
return price.value * 0.9; // 10% скидка
},
set(newValue) {
price.value = newValue / 0.9;
},
});
</script>
Теперь, когда вы вводите новое значение в поле, вычисляемое свойство автоматически изменяет исходную переменную *price* на основе скидки.
Наблюдатели (Watchers)
Теперь давайте поговорим о наблюдателях. Они позволяют *подслушивать* изменения конкретных реактивных переменных и выполнять действия в ответ на эти изменения. Если вычисляемые свойства предназначены для обработки данных, то наблюдатели отлично подходят для выполнения побочных эффектов.
Когда использовать наблюдатели?
Наблюдатели отлично подходят в случаях, когда нужно выполнять действия при изменении данных: отправить запрос на сервер, записать данные в локальное хранилище, вызвать стороннюю функцию и т.д. В отличие от вычисляемых свойств, которые просто возвращают значение, наблюдатели предназначены именно для выполнения кода.
Пример наблюдателя
Предположим, у нас есть форма с полем email, и мы хотим проверять его валидность каждый раз, когда пользователь вводит данные.
<template>
<div>
<input v-model="email" type="email" placeholder="Enter your email" />
<p v-if="!isValid">Invalid email!</p>
</div>
</template>
<script setup>
import { ref, watch } from 'vue';
const email = ref('');
const isValid = ref(true);
watch(email, (newEmail) => {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
isValid.value = emailRegex.test(newEmail);
});
</script>
Здесь наблюдатель следит за переменной *email*, и каждый раз, когда она изменяется, запускается проверка на валидность с помощью регулярного выражения.
WatchEffect: автоматическое отслеживание зависимостей
Иногда бывает сложно точно указать, за какими именно переменными мы хотим следить. В таких случаях можно использовать *watchEffect*. Это более гибкий способ создания реактивных эффектов, когда Vue автоматически отслеживает зависимости.
Пример с watchEffect:
<template>
<div>
<p>{{ message }}</p>
<button @click="increment">Increment</button>
</div>
</template>
<script setup>
import { ref, watchEffect } from 'vue';
const count = ref(0);
const message = ref('');
const increment = () => {
count.value++;
};
watchEffect(() => {
if (count.value > 5) {
message.value = 'Count is greater than 5!';
} else {
message.value = 'Keep going!';
}
});
</script>
Здесь *watchEffect* автоматически следит за переменной *count* и обновляет сообщение на экране в зависимости от её значения. Главное преимущество *watchEffect* в том, что вам не нужно явно указывать, какие переменные отслеживать — Vue сам это делает за вас.
Наблюдатели для глубоких структур данных
Иногда нам нужно отслеживать изменения в сложных объектах или массивах. Для этого в Vue можно использовать флаг *deep*, чтобы наблюдатель реагировал на вложенные изменения.
Пример с глубоким наблюдением:
<script setup>
import { ref, watch } from 'vue';
const user = ref({
name: 'Alice',
age: 25,
address: {
city: 'New York',
street: 'Broadway',
},
});
watch(user, (newUser) => {
console.log('User data changed:', newUser);
}, { deep: true });
</script>
В этом примере, если изменится любой атрибут объекта *user*, наблюдатель сработает. Без флага *deep* изменения вложенных объектов не будут отслеживаться.
Как выбрать: computed или watch?
- Используйте *computed*, когда вам нужно получить производное значение на основе других реактивных данных.
- Используйте *watch*, когда вам нужно выполнять побочные эффекты в ответ на изменения данных.
Заключение
Вычисляемые свойства и наблюдатели — это мощные инструменты Vue.js, которые позволяют гибко управлять данными и реагировать на изменения в приложении. Вычисляемые свойства облегчают работу с производными данными, обеспечивая оптимизированный и кэшированный доступ к результатам. Наблюдатели, в свою очередь, идеально подходят для выполнения действий, таких как запросы на сервер или валидация данных.
С пониманием этих концепций вы сможете создавать более эффективные и гибкие приложения на Vue 3 с использованием Composition API. В следующих статьях мы продолжим углубляться в особенности Vue, включая работу с классами, стилями и динамическими компонентами!