Vue3 #3 [변경된 기능 3 - v-for와 v-if]

템플릿 디렉티브 v-for와 v-if의 변경된 사용법을 알아보겠습니다.


Vue3는 현재 총 6편의 시리즈로 구성되어 있습니다.

  1. Vue3 #0 [Vue3를 만나다]
  2. Vue3 #1 [변경된 기능 1 - 전역 API]
  3. Vue3 #2 [변경된 기능 2 - v-model]
  4. Vue3 #3 [변경된 기능 3 - v-for와 v-if] (현재글)
  5. Vue3 #4 [새로운 기능 1 - Composition API]
  6. Vue3 #5 [새로운 기능 2 - Teleport와 Fragments]


들어가며

이번 포스팅에서도 변경된 템플릿 디렉티브 내용 중 역시 일반적으로 자주 사용되는 v-for와 v-if의 변경 점에 대하여 간단히 알아보겠습니다.


v-if

v-for와 함께 가장 많이 사용되는 디렉티브 중 하나일 것입니다.

<a v-if="isShow" class="btn">button</a>

가장 기본적인 2.x버전에서의 사용 방법이고 아무런 문제가 없습니다만, 스타일 가이드 D규칙에 따르면 다음과 같이 v-if/v-else-if/v-else에도 고유한 key를 배치하도록 권장하고 있습니다.

<a v-if="isShow" :key="on" class="btn">button</a>
<span v-else :key="off" class="btn disalble">button</span>

이제 3버전부터는 Vue가 알아서 고유한 키를 생성해주기 때문에 key설정이 필요 없어졌습니다. 그렇다고 해서 수동으로 key를 설정하는 것이 불가능한 것은 아니므로 여전히 2.x버전의 방법이 유효합니다. (수동으로 key를 설정할 때는 값이 고유한지 잘 확인해야겠죠.)


v-for

2.x 버전에서 v-for를 다룰 때 다음과 같이 많이 사용하셨을 겁니다.

<ul>
	<template v-for="{item, index} in array">
		<li :key="index">{{ item }}</li>
	</template>
</ul>

2.x버전의 스타일 가이드에 따르면 v-for 사용 시에는 key를 가지도록 필수사항으로 지정했습니다. 다만 template에 사용된 v-for는 key를 가질 수 없기 때문에 자식 요소에 key를 설정해야 했습니다.

이제 3버전부터는 template에 key를 지정해야 합니다.

<ul>
	<template v-for="{item, index} in array" :key="index">
		<li>{{ item }}</li>
	</template>
</ul>

v-if와 v-for의 동시사용..?

우선 공식 홈페이지의 마이그레이션 관련 내용입니다.


2.x 구문

2.x에서는 동일한 엘리먼트에 v-if와 v-for를 함께 사용할 때, v-for가 더 높은 우선순위를 갖습니다.

3.x 구문

3.x에서는 v-if가 항상 v-for 보다 더 높은 우선순위를 갖습니다.


이번 포스팅을 준비하면서 가장 헷갈렸던 부분입니다. 2.x버전의 스타일 가이드 필수 사항으로 v-if와 v-for는 동일한 엘리먼트에 사용하는 것을 금지했었습니다.

<li v-for="item in array" v-if="item.show">{{ item.text }}</li> // 금지

어째서인지 vue3 공식 홈페이지에 따르면 두 가지 디렉티브의 동시사용에 대하여 다음과 같이 언급하고 있습니다.

권장하는 방법은 아니지만, 필요한 경우가 있을 수 있기에, 두 디렉티브를 함께 사용할 때 어떻게 동작하는지에 대한 지침을 제공하고자 합니다.

여전히 스타일 가이드에서는 A등급으로 동시사용을 금지하고 있지만, 일종의 안내 차원에서 해당 내용을 설명하고 있는 것 같아요. 현재로서는 내부적으로 어떤 것이 우선순위를 갖는지 정도로 이해하고 있으면 될 것 같습니다. 이 내용을 보충학습 할 기회가 생기면 추후의 포스팅에서 별도의 내용을 마련하도록 하겠습니다.


v-for Array Refs

2.x버전에서 v-for를 사용한 엘리먼트에 ref를 지정하면 어떤지 알아보겠습니다. 먼저 테스트를 위하여 다음 코드를 작성해줍니다.

<div v-for="{ item , index } in list" :key="index" ref="listRef">{{ item }}</div>

콘솔 창에서 위 코드를 확인해보면 $refs 프로퍼티에 접근 가능한 배열이 생성되었음을 알 수 있습니다.

this.$vm.$refs.listRef // refs 배열에 접근 가능

3버전부터는 기존처럼 자동으로 참조 배열을 생성해주지 않도록 변경되었습니다. 바뀐 내용에 대해서는 공식 홈페이지의 예시 코드를 볼까요?

// Options API
export default {
  data() {
    return {
      itemRefs: []
    }
  },
  methods: {
    setItemRef(el) {
      this.itemRefs.push(el)
    }
  },
  beforeUpdate() {
    this.itemRefs = []
  },
  updated() {
    console.log(this.itemRefs)
  }
}

// Composition API
import { ref, onBeforeUpdate, onUpdated } from 'vue'

export default {
  setup() {
    let itemRefs = []
    const setItemRef = el => {
      itemRefs.push(el)
    }
    onBeforeUpdate(() => {
      itemRefs = []
    })
    onUpdated(() => {
      console.log(itemRefs)
    })
    return {
      itemRefs,
      setItemRef
    }
  }
}

배열은 직접 선언하였고 함수를 ref에 바인딩했습니다. 라이프 사이클 훅을 통하여 배열이 유연하게 갱신되도록 합니다. 여기에서 눈여겨볼 점은 바로 setup이라는 새로운 API가 사용된 부분입니다.

Vue3에서 새롭게 도입된 API인데 먼저 간단하게 짚어볼게요.

2.x버전에서는 data, methods 등의 옵션 API들이 동일 계층에서 선언되었습니다만, 3버전에서는 setup이라는 새로운 API를 도입하고 해당 method 안에서 작성하도록 변경되었습니다.

이는 매우 중요한데, 단순히 API만 변경된 것이 아니라 템플릿을 작성하는 방법이나 data와 method를 다루는 전반적인 방법이 변경되었기 때문입니다. 다룰 내용이 많아서 저도 더 열심히 공부하여 다음 포스팅에서 변경된 내용을 전반적으로 살펴보는 시간을 가지겠습니다.


마치며

이번 포스팅도 가장 빈번하게 사용되는 두가지 디렉티브에 대해서 알아보았습니다. 2.x버전과 비교해서 크게 달라진것 같진 않지만 사용빈도가 높은 만큼 확실하게 알아두어야 편하겠죠. 다음 포스팅은 Composition API 입니다.

그럼, 안녕히 계세요.


참고자료