← Назад к вопросам
В чем разница между вычисляемыми свойствами и секцией data?
2.2 Middle🔥 191 комментариев
#Vue.js
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Вычисляемые свойства (computed) и data секция
В Vue.js data и computed — это два различных способа хранения и предоставления состояния компонента. Хотя оба доступны через this в шаблоне, они имеют разные назначение, производительность и поведение.
Основные различия
| Параметр | data | computed |
|---|---|---|
| Назначение | Хранение реактивного состояния | Производные значения на основе data |
| Изменяемость | Может быть изменено напрямую | Только для чтения (или с setter) |
| Пересчет | Не пересчитывается | Кэшируется, пересчитывается при изменении зависимостей |
| Синтаксис | data() { return { ... } } | computed: { ... } |
| Использование | Для хранения исходных данных | Для трансформации/комбинирования data |
Data секция
Data используется для хранения реактивного состояния компонента. Каждое изменение в data немедленно обновляет компонент.
export default {
data() {
return {
firstName: "Alice",
lastName: "Johnson",
count: 0,
user: {
id: 1,
email: "alice@example.com"
}
};
}
};
<template>
<div>
<p>{{ firstName }}</p> <!-- Выводит: Alice -->
<p>{{ lastName }}</p> <!-- Выводит: Johnson -->
<button @click="count++">Счетчик: {{ count }}</button>
</div>
</template>
Computed свойства
Computed используются для создания производных значений из data. Они автоматически пересчитываются только когда изменяется их зависимость.
export default {
data() {
return {
firstName: "Alice",
lastName: "Johnson"
};
},
computed: {
// Геттер (по умолчанию)
fullName() {
return `${this.firstName} ${this.lastName}`;
}
}
};
<template>
<div>
<p>{{ fullName }}</p> <!-- Выводит: Alice Johnson -->
<input v-model="firstName" />
<!-- При изменении firstName автоматически пересчитается fullName -->
</div>
</template>
Кэширование vs Method
Важная особенность computed — кэширование. Значение пересчитывается только если изменилась его зависимость.
export default {
data() {
return {
count: 0
};
},
computed: {
// Кэшируется, пересчитывается только при изменении count
doubleCount() {
console.log("Вычисляю doubleCount");
return this.count * 2;
}
},
methods: {
// Вызывается каждый раз, без кэширования
doubleCountMethod() {
console.log("Вычисляю через метод");
return this.count * 2;
}
}
};
<template>
<div>
<!-- Вызывается 1 раз, результат кэшируется -->
<p>{{ doubleCount }}</p>
<p>{{ doubleCount }}</p>
<!-- Вызывается 2 раза -->
<p>{{ doubleCountMethod() }}</p>
<p>{{ doubleCountMethod() }}</p>
</div>
</template>
Выход консоли:
Вычисляю doubleCount // 1 раз
Вычисляю через метод // 1 раз
Вычисляю через метод // 2 раз
Setter в computed свойствах
export default {
data() {
return {
firstName: "Alice",
lastName: "Johnson"
};
},
computed: {
// Полный синтаксис с getter и setter
fullName: {
get() {
return `${this.firstName} ${this.lastName}`;
},
set(value) {
const names = value.split(" ");
this.firstName = names[0];
this.lastName = names[1];
}
}
}
};
<template>
<div>
<!-- Может быть использовано в v-model -->
<input v-model="fullName" />
<!-- При изменении будет вызван setter -->
</div>
</template>
Практические примеры
1. Фильтрация списка
export default {
data() {
return {
users: [
{ id: 1, name: "Alice", active: true },
{ id: 2, name: "Bob", active: false },
{ id: 3, name: "Charlie", active: true }
],
searchQuery: ""
};
},
computed: {
// Пересчитывается только при изменении users или searchQuery
filteredUsers() {
return this.users.filter(user =>
user.name.toLowerCase().includes(this.searchQuery.toLowerCase())
);
}
}
};
<template>
<div>
<input v-model="searchQuery" placeholder="Поиск..." />
<ul>
<li v-for="user in filteredUsers" :key="user.id">
{{ user.name }}
</li>
</ul>
</div>
</template>
2. Сложные вычисления
export default {
data() {
return {
price: 100,
quantity: 5,
taxRate: 0.1
};
},
computed: {
subtotal() {
return this.price * this.quantity;
},
tax() {
return this.subtotal * this.taxRate;
},
total() {
return this.subtotal + this.tax;
}
}
};
<template>
<div>
<p>Подитого: ${{ subtotal }}</p>
<p>Налог: ${{ tax }}</p>
<p>Итого: ${{ total }}</p>
</div>
</template>
3. Статусные вычисления
export default {
data() {
return {
password: "",
confirmPassword: ""
};
},
computed: {
isPasswordValid() {
return this.password.length >= 8;
},
passwordsMatch() {
return this.password === this.confirmPassword;
},
canSubmit() {
return this.isPasswordValid && this.passwordsMatch;
}
}
};
<template>
<form>
<input
v-model="password"
type="password"
placeholder="Пароль"
/>
<input
v-model="confirmPassword"
type="password"
placeholder="Подтвердите пароль"
/>
<button :disabled="!canSubmit">Отправить</button>
</form>
</template>
Производительность
// Плохо: дорогое вычисление в шаблоне
export default {
data() {
return {
items: []
};
}
};
<!-- Это вычисляется каждый раз при рендере -->
<p>{{ items.filter(item => item.active).map(item => item.name).join(", ") }}</p>
<!-- Даже если items не изменились -->
// Хорошо: используй computed
export default {
data() {
return {
items: []
};
},
computed: {
// Кэшируется и пересчитывается только при изменении items
activeItemNames() {
return this.items
.filter(item => item.active)
.map(item => item.name)
.join(", ");
}
}
};
<p>{{ activeItemNames }}</p>
Когда использовать что
Используй data для:
- Исходных данных формы
- Состояния компонента
- Флагов видимости
- Загруженных данных с сервера
data() {
return {
formData: { name: "", email: "" },
isLoading: false,
isModalOpen: false
};
}
Используй computed для:
- Производных значений
- Преобразований данных
- Фильтраций и сортировок
- Проверок статуса
- Комбинирования нескольких data свойств
computed: {
displayName() {
return `${this.firstName} ${this.lastName}`;
},
isValid() {
return this.email && this.password.length >= 8;
}
}
Вывод
- data — хранилище реактивного состояния, изменяется напрямую
- computed — производные значения, автоматически пересчитываются
- computed кэшируется, что улучшает производительность
- Используй data для исходных данных, computed для преобразований
- Не вычисляй сложное в шаблоне — выноси в computed
- computed имеет доступ к
this(текущему контексту компонента)