21. understanding the role of the key attribute
내용
이 강의에서는 "key" 속성의 중요성과 사용 이유를 설명합니다. "key" 속성은 Vue.js에서 리스트 렌더링 시 요소를 고유하게 식별하고 재배치할 때 사용됩니다.
우선 문제를 이해하기 위해 예시를 제시합니다. 데이터 배열을 루핑하고 이를 템플릿에 렌더링하는 간단한 애플리케이션을 소개합니다. 그런 다음, 배열의 첫 번째 항목을 마지막 항목으로 이동시키는 버튼을 추가합니다.
문제는 리스트에 대한 루핑과 이동 작업을 수행하는 동안 일어납니다. 버튼을 눌렀을 때, 데이터 이동은 잘 작동하지만, 텍스트 내용은 이동하지 않고 그대로 남아있습니다. 이것이 발생하는 이유는 Vue.js가 성능상의 이유로 요소를 템플릿에서 제거하거나 추가하지 않기 때문입니다.
이 문제를 해결하기 위해 "key" 속성을 사용합니다. "key" 속성은 각 항목을 고유하게 식별하는 데 사용되며, Vue.js에게 요소 이동을 강제합니다. 따라서 데이터가 이동할 때 요소도 함께 이동하게 됩니다.
"key" 속성을 사용하면 요소 이동은 성능에 부담이 될 수 있지만, 예상치 못한 동작을 방지할 수 있습니다. 특히 복잡한 애플리케이션에서는 "key" 속성이 매우 유용하며, 요소가 루프 내에서 예상대로 작동하지 않을 때 "key" 속성을 추가하는 것을 권장합니다.
또한 강의 리소스 섹션에 "key" 속성 및 리스트 렌더링에 대한 자세한 정보가 있는 링크를 제공하므로 참고할 수 있습니다.
index.html
<!DOCTYPE>
<html>
<head>
<title>VueJS Course</title>
<link rel="stylesheet" type="text/css" href="main.css" />
</head>
<body>
<div id="app">
<button type="button" class="move" @click="move">
Move to Bottom
</button>
<div class="card" v-for="person in people">
<h3>{{ person.name }}</h3>
<p>{{ person.message }}</p>
<input type="text" />
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/3.4.6/vue.global.prod.min.js"></script>
<script src="app.js"></script>
</body>
</html>
app.js
let vm = Vue.createApp({
data() {
return {
people: [
{
name: 'John',
message: 'Hello world!'
},
{
name: 'Rick',
message: 'I like pie.'
},
{
name: 'Amy',
message: 'Skydiving is fun!'
}
]
}
},
methods: {
move() {
const first = this.people.shift()
this.people.push(first)
}
}
}).mount('#app')
main.css
body {
font-size: 20px;
font-family: sans-serif;
padding-top: 10px;
background: #e6ecf1;
}
#app {
text-align: center;
}
#app button {
background-color: #899ff4;
border-color: transparent;
color: #fff;
font-size: 20px;
padding: 10px;
margin-bottom: 10px;
}
#app .card {
width: 400px;
margin: 15px auto;
padding-bottom: 15px;
background-color: #fff;
box-shadow: 0 2px 3px rgba(10, 10, 10, 0.1), 0 0 0 1px rgba(10, 10, 10, 0.1);
color: #4a4a4a;
display: block;
padding: 1.25rem;
}
#app input:focus {
outline: 0;
}
#app input {
font-weight: bold;
width: 100%;
font-size: 1em;
padding: 5px 10px;
}
index.html
<!DOCTYPE>
<html>
<head>
<title>VueJS Course</title>
<link rel="stylesheet" type="text/css" href="main.css" />
</head>
<body>
<div id="app">
<button type="button" class="move" @click="move">
Move to Bottom
</button>
<div class="card" v-for="person in people" :key="person.name">
<h3>{{ person.name }}</h3>
<p>{{ person.message }}</p>
<input type="text" />
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/3.4.6/vue.global.prod.min.js"></script>
<script src="app.js"></script>
</body>
</html>
app.js
let vm = Vue.createApp({
data() {
return {
people: [
{
name: 'John',
message: 'Hello world!'
},
{
name: 'Rick',
message: 'I like pie.'
},
{
name: 'Amy',
message: 'Skydiving is fun!'
}
]
}
},
methods: {
move() {
const first = this.people.shift()
this.people.push(first)
}
}
}).mount('#app')
main.css
body {
font-size: 20px;
font-family: sans-serif;
padding-top: 10px;
background: #e6ecf1;
}
#app {
text-align: center;
}
#app button {
background-color: #899ff4;
border-color: transparent;
color: #fff;
font-size: 20px;
padding: 10px;
margin-bottom: 10px;
}
#app .card {
width: 400px;
margin: 15px auto;
padding-bottom: 15px;
background-color: #fff;
box-shadow: 0 2px 3px rgba(10, 10, 10, 0.1), 0 0 0 1px rgba(10, 10, 10, 0.1);
color: #4a4a4a;
display: block;
padding: 1.25rem;
}
#app input:focus {
outline: 0;
}
#app input {
font-weight: bold;
width: 100%;
font-size: 1em;
padding: 5px 10px;
}