Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Атрибут Key во Vue: Назначение и Практика
Атрибут key в Vue.js — это инструмент для управления идентификацией элементов при рендеринге списков. Это критически важный концепт для корректной работы виртуального DOM.
Основное назначение Key
Key помогает Vue отследить, какой элемент в списке соответствует какому элементу DOM, когда список изменяется. Без key Vue может перезаписывать данные в существующих элементах вместо того, чтобы переупорядочивать их.
<!-- Плохо: без key -->
<template>
<ul>
<li v-for="item in items">
{{ item.name }}
<input v-model="item.description" />
</li>
</ul>
</template>
<!-- Хорошо: с key -->
<template>
<ul>
<li v-for="item in items" :key="item.id">
{{ item.name }}
<input v-model="item.description" />
</li>
</ul>
</template>
Проблема без Key
// Начальные данные
const items = [
{ id: 1, name: 'Alice', description: '' },
{ id: 2, name: 'Bob', description: '' },
{ id: 3, name: 'Charlie', description: '' },
];
// Пользователь вводит текст в первый input
// items[0].description = 'Some text'
// Потом добавляется новый элемент в начало
items.unshift({ id: 4, name: 'Diana', description: '' });
// БЕЗ KEY:
// Vue просто обновит текст первого элемента
// input всё ещё содержит "Some text", но теперь это Diana, а не Alice!
// Бага! Данные потеряны!
// С KEY='item.id':
// Vue знает, что элемент с id=1 всё ещё Alice
// и переместит его в правильное место
// input останется с Alice, как и ожидается
Когда Key Критичен
1. Состояние компонента в списке
<template>
<div>
<button @click="addItem">Добавить</button>
<ul>
<li v-for="item in items" :key="item.id">
<p>{{ item.name }}</p>
<!-- У каждого li может быть своё состояние -->
<input v-model="item.comment" />
<input type="checkbox" v-model="item.done" />
</li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
items: [
{ id: 1, name: 'Task 1', comment: '', done: false },
{ id: 2, name: 'Task 2', comment: '', done: false },
],
};
},
methods: {
addItem() {
// Добавляем в начало
this.items.unshift({
id: Date.now(),
name: `Task ${this.items.length + 1}`,
comment: '',
done: false,
});
// С key, состояние каждого элемента остаётся правильным
},
},
};
</script>
2. Transition и анимации
<template>
<transition-group name="list" tag="ul">
<li v-for="item in items" :key="item.id" class="list-item">
{{ item.name }}
</li>
</transition-group>
</template>
<style scoped>
.list-enter-active,
.list-leave-active {
transition: all 0.5s;
}
.list-enter-from,
.list-leave-to {
opacity: 0;
transform: translateX(-30px);
}
</style>
<!-- БЕЗ key анимации будут неправильными,
потому что Vue не поймёт какой элемент уходит/приходит -->
3. Форма внутри списка
<template>
<form v-for="user in users" :key="user.id">
<input v-model="user.name" placeholder="Имя" />
<input v-model="user.email" placeholder="Email" />
<button @click="saveUser(user)">Сохранить</button>
</form>
</template>
<script>
export default {
data() {
return {
users: [
{ id: 1, name: 'John', email: 'john@example.com' },
{ id: 2, name: 'Jane', email: 'jane@example.com' },
],
};
},
methods: {
saveUser(user) {
// Сохраняем данные текущего пользователя
api.updateUser(user);
},
},
};
</script>
Когда НЕ нужен Key
Ситуация 1: Список не меняется
<!-- OK без key, так как список статический -->
<ul>
<li v-for="country in countries">
{{ country.name }}
</li>
</ul>
Ситуация 2: Просто отображаем данные без состояния
<!-- OK без key, если нет input/чекбоксов/состояния -->
<div v-for="post in posts">
<h2>{{ post.title }}</h2>
<p>{{ post.content }}</p>
</div>
Best Practices для Key
✅ ПРАВИЛЬНО: Уникальный идентификатор
<!-- Идеальный вариант -->
<li v-for="user in users" :key="user.id">
{{ user.name }}
</li>
<!-- Если нет id, создаём UUID -->
<li v-for="item in items" :key="item.uuid">
{{ item.name }}
</li>
❌ НЕПРАВИЛЬНО: Index в качестве key
<!-- НИКОГДА не делай так! -->
<li v-for="(item, index) in items" :key="index">
{{ item.name }}
</li>
<!-- Почему плохо:
- Если элемент удаляется/переупорядочивается, index меняется
- Vue потеряет связь между элементом и его DOM
- Состояние элемента может смешаться
-->
Пример проблемы с index:
// Начально
items = [
{ id: 1, name: 'Alice' }, // key=0
{ id: 2, name: 'Bob' }, // key=1
{ id: 3, name: 'Charlie' }, // key=2
];
// Удаляем Alice
items.shift();
// Теперь
items = [
{ id: 2, name: 'Bob' }, // key=0 (был 1)
{ id: 3, name: 'Charlie' }, // key=1 (был 2)
];
// Vue переиспользует элементы DOM, что вызовет баги!
// Это особенно проблематично с input и состоянием
Key в Composition API
<script setup lang="ts">
import { ref } from 'vue';
interface Task {
id: number;
title: string;
completed: boolean;
}
const tasks = ref<Task[]>([
{ id: 1, title: 'Learn Vue', completed: false },
{ id: 2, title: 'Build App', completed: false },
]);
const addTask = () => {
tasks.value.unshift({
id: Date.now(),
title: 'New Task',
completed: false,
});
};
</script>
<template>
<button @click="addTask">Добавить задачу</button>
<ul>
<!-- key="task.id" обязателен для правильной работы -->
<li v-for="task in tasks" :key="task.id">
<input type="checkbox" v-model="task.completed" />
{{ task.title }}
</li>
</ul>
</template>
Key в v-if / v-else
<template>
<div>
<input v-if="showPassword" type="text" :key="'password-text'" />
<input v-else type="password" :key="'password-field'" />
<button @click="showPassword = !showPassword">Toggle</button>
</div>
</template>
<script>
export default {
data() {
return {
showPassword: false,
};
},
};
</script>
<!-- Key помогает Vue переиспользовать или пересоздавать element правильно -->
Сравнение с React
Vue:
<li v-for="item in items" :key="item.id">
{{ item.name }}
</li>
React:
{items.map((item) => (
<li key={item.id}>
{item.name}
</li>
))}
Концепция одинаковая, синтаксис разный.
На собеседовании
Полный ответ должен показать:
- Основное назначение — помощь Vue отследить элементы
- Проблемы без key — конкретные примеры с input/состоянием
- Когда key критичен — список с состоянием, анимации
- Best practices — использовать id, не index
- Сравнение с React — показать понимание виртуального DOM
- Performance — как key влияет на рендеринг