Vue.js의 리스트 렌더링의 개념에 대해 알아보도록 합시다. 더욱 자세한 사항은 공식 문서를 참고해주시기 바랍니다.
v-for
디렉티브를 사용하여 배열을 기반으로 리스트를 렌더링 할 수 있습니다. v-for
디렉티브는 fruit in fruits
형태로 특별한 문법이 필요합니다. 여기서 fruits
는 원본 데이터 배열이고 fruit
은 반복되는 배열 엘리먼트의 별칭입니다.
<template>
<ul>
<li
v-for="fruit in fruits"
:key="fruit">
{{ fruit }}
</li>
</ul>
</template>
v-for
블록 안에는 부모 범위 속성에 대한 모든 권한이 있습니다. v-for
는 또한 현재 항목의 인덱스에 대한 두 번째 전달인자 옵션을 제공합니다.
<template>
<ul>
<li
v-for="(fruit, index) in fruits"
:key="fruit">
{{ fruit }}-{{ index }}
</li>
</ul>
</template>
<script>
export default {
data() {
return {
fruits: ['Apple', 'Banana', 'Cherry']
}
}
}
</script>
원래 데이터를 실제로 변경하거나 재설정하지 않고, 배열의 필터링되거나 정렬된 버전을 표시할 수도 있습니다. 이 경우 필터링되거나 정렬된 배열을 반환하는 computed
속성을 만들 수 있습니다.
<template>
<ul>
<li
v-for="fruit in newFruits"
:key="fruit.id">
{{ fruit.name }}
</li>
</ul>
</template>
<script>
export default {
data() {
return {
fruits: ['Apple', 'Banana', 'Cherry']
}
},
computed: {
newFruits() {
return this.fruits.map((fruit, index) => {
return {
id: index,
name: fruit
}
})
}
}
}
</script>
실제로 프로젝트를 진행하게 되면, 위와 같이 fruits와 같은 단순한 배열 구조가 아닌 newFruits()와 마찬가지로 배열 데이터 안에 객체 데이터가 있고, 그 객체 데이터 안에는 복잡한 구조로 여러가지 속성들로 데이터가 구분되어 있는 형태로 제공되는 데이터를 활용하게 됩니다.
그러한 데이터들을 화면에 반복적으로 출력하기 위해서는 위와 같은 방법으로 v-for
디렉티브를 작성하셔야 합니다. 특히, v-for
디렉티브를 사용하게 되면 반드시 :key
값으로 배열의 아이템들을 고유하게 구분해줄 수 있는 특정한 속성이 존재해야 하며 이를 통해 화면에 출력되는 내용을 최적화할 수 있습니다.
위와 같은 설명에 덧붙여 :key
값에 들어갈 id값을 고유하게 구분해줄 수 있도록 하는 shortid라는 패키지가 있으며, 이를 설치하여 사용해보도록 합시다.
$ npm i -D shortid
<script>
import shortid from 'shortid' // 설치한 패키지 가져오기
export default {
data() {
return {
fruits: ['Apple', 'Banana', 'Cherry']
}
},
computed: {
newFruits() {
return this.fruits.map(fruit => ({
id: shortid.generate(), // shortid를 생성하는 generate() 메소드 실행
name: fruit
}))
}
}
}
</script>
이러한 패키지를 통해 고유한 값이 필요한 곳에서 손쉽게 만들어낼 수 있습니다.
Vue는 감시 중인 변이 메소드를 래핑하면(배열의 데이터를 변경하면) 화면에 출력이 갱신되는 반응성을 갖고 있습니다. 래핑된 메소드는 다음과 같습니다.
이름에서 알 수 있듯이 변이 메소드는 호출된 원래 배열을 변경합니다. 이에 비해 filter()
, concat()
그리고 slice()
와 같은 원래 배열을 변경하지는 않지만 항상 새 배열을 반환하는 비-변이 메소드도 있습니다. 비-변이 메소드로 작업할 때 이전 배열을 새 배열로 바꿀 수 있습니다.
example1.items = example1.items.filter(item => item.message.match(/Foo/))
이로 인해 Vue가 기존 DOM을 버리고 전체 목록을 다시 렌더링할 것이라고 생각할 수 있습니다. 다행히도 그렇지 않습니다. Vue는 DOM 요소 재사용을 최대화하기 위해 몇 가지 smart heuristics(스마트 휴리스틱, 과학적인 조건보다는 경험이나 직관에 의해 똑똑하게 의사결정을 하는 방식)을 구현하므로, 배열을 겹치는 객체를 포함하는 다른 배열로 교체하는 것은 매우 효율적인 작업입니다.