cover

사이트를 둘러보면 동일한 형태로 내용만 달라지는 것들이 있습니다. 유튜브의 영상 목록이나 사이드바의 메뉴 같은 것들이 있죠. 일일이 HTML로 작성하는 것은 보기도 안좋고 편하지도 않습니다. Vue에서는 for문처럼 이런 태그를 반복할 수 있는 디렉티브 v-for를 제공합니다. 자세히 알아볼까요?


v-for 미리보기

v-for

v-for 디렉티브는 배열이나 객체를 반복하여 렌더링할 수 있도록 도와줍니다.

v-for 문법

v-for는 다른 디렉티브와 다르게 javascript 문법이 아닌 for문처럼 반복을 위한 특수한 문법이 들어갑니다.

html
      <div v-for="item in list"></div>
<!-- 위와 동일하게 동작 -->
<div v-for="item of list"></div>
    
list: 반복해서 볼 컴포넌트의 데이터입니다.
item: 반복했을 때 값을 저장하는 변수(alias)입니다. item이 아닌 다른 명칭으로 해도 됩니다.

item은 해당 태그 내에서 컴포넌트 데이터처럼 콧수염 문법이나 데이터 바인딩을 위해 사용할 수 있습니다.

html
      <div v-for="item of list">
	<span>{{ item }}</span>
	<p :class={ item }></p>
</div>
    

v-for 배열 반복

배열을 반복할 때는 (값, 인덱스) in array 형태로 반복할 수 있습니다. 인덱스를 생략하는 경우 위에서 봤던 문법처럼 됩니다.

html
      <div v-for="(value, index) in array">{{ index }} {{ value }}</div>
<!-- index 생략 가능 -->
<div v-for="value in array">{{ value }}</div>
    
value: 배열의 값이 하나씩 차례로 들어갑니다.
index: 인덱스 값입니다.(0부터 시작)

v-for 배열 속 배열

배열 안에 있는 값은 문자열, 숫자, 객체 등 무엇이든 가능합니다. 그래서 배열 속에 배열이 있는 경우 중첩해서 반복할 수 있습니다.

html
      
<div v-for="innerArray in array">
	<div v-for="item of innerArray">{{ item }}</div>
</div>
    

v-for 객체 반복

객체를 반복할 때도 동 일한잃형의 법문을 사용합니다. 다만 객체에는 키도 존재하죠. 그래서 값, 키, 인덱스 순으로 가져올 수 있습니다.

html
      <태그 v-for="(value, key, index) in 객체">{{ index }} {{ key }} {{ value }}</태그>

<!-- index 생략 -->
<태그 v-for="(value, key) in 객체">{{ key }} {{ value }}</태그>

<!-- key와 index 생략 -->
<태그 v-for="value in 객체">{{ value }}</태그>
    

배열과 마찬가지로 값(value)에는 객체나 배열도 들어갈 수 있어서 중첩 반복이 가능합니다.

html
      <태그 v-for="(key, val) in object">
	<태그 v-for="(key, item, index) of val.children">{{ item }}</태그>
</태그>
    

v-for 객체의 배열

객체 안의 객체, 배열 안에 배열 이렇게도 된다면 객체의 배열이나 배열의 객체도 되겠죠? 예를 들어 다음과 같이 객체들의 배열이 있다고 해볼게요.

javascript
      // ...
data() {
	return {
		people: [
			{ name: "Hans", email: "hans@gmail.com", age: 17 },
			{ name: "Elsa", email: "elsa@naver.com", age: 15 },
			{ name: "Anna", email: "anna@daum.net", age: 14 },
		]
	}
}
// ...
    

이를 반복문을 통해 불러오고 해당 값을 객체에 접근하듯 객체.키 형태로 불러오면 됩니다. Javascript 문법이 되니까요!

html
      <div v-for="p of people">
	{{ p.name }}, {{ p.email }}, {{ p.age }}
</div>
    

구조 분해 할당 (Destructuring assignment)

Javascript에서 처럼 객체 내부 값을 구조 분해 할당하는 것도 가능합니다.

html
      <div v-for="{ name, email, age } of people">
	{{ name }}, {{ email }}, {{ age }}
</div>
    

v-for와 key는 단짝

v-for는 잘 동작하는 것처럼 보이지만 한 가지 문제가 발생합니다. 다음 예시에서 순서 바꾸기 버튼을 눌러보세요.

위 코드에서 중요한 곳은 반복하는 곳입니다. 만약 nums의 순서를 바꾸면 반복문 안의 내용들도 같이 순서가 바뀌었을 거라 예상하지만 그렇지 않죠.

html
      <p v-for="num of nums">
	<span>{{ num }}</span>
	<span> | </span>
	<span class="number"></span>
</p>
    

v-for는 기본적으로 in-place-patch 방식으로 갱신합니다. 쉽게 말하면 바뀐 곳만 땜빵(patch)으로 고친다는 뜻입니다. 그래서 실제로 태그가 움직인게 아니라 숫자만 바뀐 것이죠. nums와 관련없었던 .number 태그의 값들은 그대로인 이유입니다.

공식 Vue.js 스타일 가이드에서는 key 속성을 항상 넣어주길 권장합니다.

html
      <태그 v-for="num of nums" :key="num"></태그>
    
info
      key에 들어가는 값은 객체나 배열이 아닌 기본 타입(숫자나 문자열)을 사용해야 하고 다른 값들과 구별되는 유일한(Unique) 값이여야 합니다. 
    

v-for 일정 개수를 반복

어떤 배열이나 객체를 반복하는 게 아니라 몇 번 반복해서 렌더링하고 싶을 수도 있습니다. 그러면 정수를 쓰세요!

html
      <태그 v-for="n in 5"></태그>
    
info
      n은 0이 아닌 1부터 시작합니다!
    

컴포넌트와 template

일반적인 태그뿐만 아니라 컴포넌트, template 태그에서도 사용 가능합니다.

html
      <MyComponent
  v-for="(item, index) in items"
  :item="item"
  :index="index"
  :key="item.id"
/>
    
html
      <ul>
  <template v-for="item in items">
    <li>{{ item.msg }}</li>
    <li class="divider" role="presentation"></li>
  </template>
</ul>
    

v-for와 v-if를 같이 쓰면?

v-for와 v-if를 한 태그 안에서 같이 쓰는 것은 권장하고 있지 않은 방법입니다. 하지만 이는 v-if에서 이미 다루었기 때문에 자세히 보진 않겠습니다.

v-for 배열 변화주는 함수들

배열 관련된 함수들이 많이 있습니다. 아래 함수들은 실행하는 것만으로도 배열 원본을 바꿉니다.

push()
pop()
shift()
unshift()
splice()
sort()
reverse()

이 함수들을 실행하는 경우 Vue는 이를 파악해서 알아서 기존 DOM을 바꿔서 렌더링해줍니다. 그런데 변화된 결과를 반환하는 함수들도 있습니다.

fliter()
concat()
slice()

이런 함수들은 아쉽게도 Vue가 실행했을 때 바꿔주지 않습니다. 그러면 반환한 값을 새로 쓰면 될 것 같은데요.

javascript
      this.list = this.list.filter(...)
    

아쉽게도 이는 반영되지 않습니다. 아래 예시는 1부터 5까지 숫자를 filter를 이용해 제곱으로 바꾸는 예시입니다.

그러면 이 경우는 어떻게 해야할까요. computedmethods를 사용하면 됩니다.

마무리하며

이번 글에서는 리스트를 편하게 반복할 수 있는 v-for에 대해 알아봤습니다. 다음부터는