Vue.js | 조건 분기 및 산출 속성

조건에 따라 요소나 특성 등의 내용을 표시/숨기기로 전환하려면 v-show v-if 지시자 속성을 사용한다.

  • Vue 2.5.4

v-show와 v-if의 차이

둘 사이의 차이는 v-show는 CSS에서 display : none으로 단순히 화면에서만 숨길 수 있는 반면 v-if는 DOM 레벨로 존재를 삭제한다.

표시와 숨기기를 여러번 전환하는 경우는 v-show를 사용하는 것이 성능으로 좋다. 그러나 v-show 보이지 않아도 내부는 계속 상황을 모니터링하고 있다.

내부 데이터가 많거나 특정 객체를 가지고 있지 않으면 오류가 발생하는 등 단순히 숨겨져 있는 상태에서 처리를 시키고 싶지 않은 경우는 v-if를 사용하면 좋다.

목록에 특정 조건을 만족하는 데이터만 표시

다음 데이터를 사용하여 입력한 수치 이하의 제품만 표시하도록 싶다.

new Vue({
  el: '#app',
  data: {
    price: 300,
    inputprice: 200,
    list: [{
      name: '토마토',
      price: 100
    }, {
      name: '상추',
      price: 200
    }, {
      name: '오이',
      price: 300
    }]
  }
})

작성법은 v-showv-if도 동일하게 다음과 같다.

<li v-for="val in list" v-show="조건식">조건을 만족하는 조건을 만족하면 표시된다.</li>

조건식 부분에는 JavaScript의 if문 괄호 안에 쓰는 것과 같은 식을 넣는다. 메소드명이라면 부울 값을 나타내는 데이터를 전달하면 된다.

<ul>
    <!-- val.price가 입력된 price 보다도 작다면 표시 -->
    <li v-for="val in list" v-show="val.price <= price">
    {{ val.name }} {{ val.price }} 원
     </li>
</ul>
<input v-model.number="inputprice" size="5"> 원 이하의 상품 표시보기
<!-- 버튼을 누르면 price가 갱신되고 동시에 결과도 갱신된다. -->
<button @click="price = inputprice">click!</button>

v-model에 연결되어 있는 inputprice 값을 사용하면 실시간으로 검색되지만, 이번에는 버튼을 누른 타이밍에서 검색하려고 했기에 price라는 데이터 입력 값을 대입하여 그것을 조건으로 사용하도록 했다.

코드 실행

숫자를 입력하고 클릭하면 그 이하의 가격의 상품만 표시가 되었다. 실제로는 숫자 외에 값이 입력된 경우의 처리가 필요하지만 실시간 필터링이 되는 간단히 가능한 기능만 확인하도록 하자.

덧붙여서 v-model에는 입력 값을 숫자로 변환시키는 수식어(.number)도 포함되어 있다.

스타일과 클래스에 조건을 붙인다.

<ul>
    <li v-for="val in list" v-show="!price || val.price <= price">
        {{ val.name }} <span v-bind:style="{color: val.price <= 200 ? 'red' : 'blue'}">{{ val.price }}원</span>
    </li>
</ul>

코드 실행

위의 예에서는 가격이 200원 이하면 빨간색하도록 했다. style과 class는 값이 여러 개가 있을 수 있기 때문에 v-bind에는 객체 형식으로 각각에 조건을 붙일 수 있다. v-bind를 사용하지 않고 일반적으로 작성하는 style과 class가 있을 경우 병합(merge)된 결과가 표시된다.

<span :style="{ color: colorValue }">텍스트</span>
<span :class="{ active: price < 200 }">텍스트</span>

colorValue에는 수식 및 부울 값에 데이터를 쓴다. 객체 또는 가공된 문자열 데이터를 넘겨도 된다.

<span :style="styleObject">텍스트</span>

계산 속성 사용하기

그런데, 여기에 동시에 “X건을 찾았습니다"나 “아무것도 찾을 수 없습니다"와 같은 표시도 하고 싶은데, 최종적으로 검색한 데이터 개수를 어떻게 얻는 것이 좋을까? 공식 가이드를 보면 “계산된 속성"이라는 것이 있다. 데이터를 검색할 때에 처리할 수 있는 기능으로써 이를 사용한다면 가능할 것이다!

계산된 속성은 무엇인가 처리를 한 결과를 데이터 값으로 반환할 수 있다. 위의 예와 다른 점은 v-for에 전달된 시점에 이미 조건을 만족한 것만이 배열로 되어 있다는 것이다. 문자를 덧붙이거나, 불필요한 것을 제거하거나, 지금 가지고 있는 데이터로 부터 새로운 데이터를 만들거나 여러가지가 가능하다. methods와 같이 computed라는 옵션에 함수를 정의한다. 함수로 정의하고 있지만, 사용 방법은 그 이름과 같이 속성으로 사용한다.

new Vue({
  el: '#app',
  data: {
    price: 300,
    inputprice: 200,
    list: [{
      name: '토마토',
      price: 100
    }, {
      name: '상추',
      price: 200
    }, {
      name: '오이',
      price: 300
    }]
  },
  computed: {
    matchList: function() {
      console.log('matchList') // 테스트이므로 실행했을 때 로그를 남긴다.
       // 필터를 사용하여 price보다 작은 것만 배열을 만들어 반환한다.
      return this.list.filter(function(val) {
        return val.price <= this.price
      }, this)
    }
  }
})

matchList라는 이름으로 간단한 계산된 속성을 만들어 보았다.

<ul>
    <li v-for="val in matchList">
        {{ val.name }} {{ val.price }} 원
    </li>
    <li v-if="!matchList.length">
        해당하는 상품이 없습니다.
    </li>
</ul>
<input v-model.number="inputprice" size="5"> 원 이하의 상품 표시보기
<button @click="price = inputprice">click!</button>
{{ matchList.length }} 개를 찾았습니다.

계산된 속성에서 먼저 처리하고 결과의 length를 보면 검색된 수를 알 수 있다!

코드 실행

matchList을 3곳에서 사용하고 있기 때문에, 그 때마다 함수가 실행되는 있을까 하고 불안하여 console.log을 넣어 보니 한 번만 실행되었다. 계산된 속성은 그 속에서 사용하는 데이터에 변화가 있을 때까지 캐시되는 것 같다. 멋지지 않은가? 그럼 method를 사용에 이득이 있다는 것이다.

계산된 속성은 종속 관계에 의거 캐시된다는 차이가 있다.

계산된 캐싱 vs 메소드

즉, 종속 데이터에 변화가 있으면 계산된 속성도 동기화 해 버리므로, 변화되어도 즉시 표시를 갱신하고 싶지 않거나, 어떤 조건에 새로운 데이터를 만들고 싶을 때에는 다른 글에서작성 있는 watch를 사용하는 것이 좋다.

v-if / v-else-if / v-else으로 여러 조건을 설정

v-if와 함께 v-else-if, v-else 지시어를 사용할 수 있다. 반드시 조건 요소 바로 뒤에 두도록 하여 사용한다.

<div v-if="조건A">조건A</div>
<div v-else-if="조건B">조건B</div>
<div v-else>일치되지 않는다.</div>

결론

응용 프로그램을 만들려면 조건 분기는 필수이다. 계산된 속성은 굉장히 편리하다! 상황에 따라 method로 사용을 알게 되면 좋을 것이다. 다음은 드디어 구성 요소에 대해 설명하겠다.