v-if를 쓰면 항상 나오는 것이 v-show여서 궁금해서 정리해보게 되었다.
1. v-if
: v-if 디렉티브는 조건에 따라 블록을 렌더링할 때 사용된다. 블록은 디렉티브의 표현식이 true 값을 반환할 때만 렌더링된다.
<h1 v-if="awesome">Vue is awesome!</h1>
<h1 v-else>Oh no 😢</h1>
예시
<template>
<button @click="handler">Click me!</button>
<h1 v-if="isShow">Hello?!</h1>
<h1 v-else>Good~</h1>
</template>
<script>
export default {
data() {
return {
isShow: true
}
},
methods: {
handler() {
this.isShow = !this.isShow
}
}
}
</script>
코드 설명
- button을 클릭시 isShow가 true면 Hello를 출력한다.
- false라면 Good~을 출력한다.
- 이는 클릭시 핸들러 함수를 설정하여 false면 true, true면 false를 출력하게 설정하였다.
v-else-if, v-else
<div v-if="type === 'A'">
A
</div>
<div v-else-if="type === 'B'">
B
</div>
<div v-else-if="type === 'C'">
C
</div>
<div v-else>
Not A/B/C
</div>
→ 조건이 여러개일 때 v-else-if를 설정한다. 그리고 나머지 조건은 v-else로 설정할 수 있다.
순서는 v-if > v-else-if > v-else로 설정된다. 하지만 마지막 조건을 v-else로 설정 가능하지, v-else-if로 끝나면 안된다. 이럴 경우 오류가 발생한다.
두 개이상 엘리먼트 존재시
v-if는 디렉티브이기 때문에 하나의 엘리먼트에 추가되어야 한다.
둘 이상의 엘리먼트를 전환하려면, v-if를 <template>엘리먼트에 사용할 수 있다. <template>엘리먼트는 눈에 보이지 않게 내부 엘리먼트를 감싸는 역할(invisible wrapper)을 하며, 최종 렌더링 결과에 포함되지 않는다.
<template>
<button @click="handler">
Click me!
</button>
<template v-if="isShow">
<h1>Title</h1>
<p>Paragraph 1</p>
<p>Paragraph 2</p>
</template>
</template>
button 태그 안에 template 태그가 들어있지만, 엘리먼트는 눈에 보이지 않게 감싸는 역할만 하게 되는 것을 확인할 수 있다. 하지만 .vue라는 확장자의 컴포넌트의 최상위 template 태그에는 v-if를 사용해서는 안된다. 위에서 말한 것처럼 감싸는 역할을 할 뿐이지, dom에서 랜더링되는 역할 아니기에 화면에 보일 수 없다.
2. v-show
: v-if와 사용방법은 동일하다.
<h1 v-show="ok">Hello!</h1>
둘의 차이는 v-show를 쓴 엘리먼트의 경우, 항상 렌더링 되어 DOM에 남아있다. v-show는 단순히 엘리먼트의 CSS display 속성만을 전환한다. 아래처럼 v-if는 값이 false인 경우 DOM에 남아있지 않고 숨겨져 있다.
💫 그러나 v-show의 경우에는 이처럼 값이 false인 경우에도 DOM에 남아있으며 display 속성이 none으로 표시되어 있다.
v-if와 v-show의 차이
v-if는 "실제(real)" 조건부 렌더링이다. 전환 도중 조건부 블록 내부의 이벤트 리스너 및 자식 컴포넌트들이 올바르게 제거되고 다시 생성된다. 초기 렌더링 시, 조건이 거짓(false)이면 아무 작업도 하지 않는다. 조건부 블록은 조건이 처음으로 참(true)이 될 때까지 렌더링되지 않는다.
이에 비해 v-show는 훨씬 간단하다. 엘리먼트는 CSS 기반 전환으로 초기 조건과 관계 없이 항상 렌더링된다.
💫 일반적으로 v-if는 전환 비용이 높은 반면, v-show는 초기 렌더링 비용이 높다. 자주 전환이 필요다면
v-show를 사용하는 게 좋고, 런타임 시 조건이 변경되지 않는다면 v-if를 사용하는 게 더 낫다.
🔗 참고
https://velog.velcdn.com/images%2Fhanei100%2Fpost%2F94fae37b-9f67-4d26-84ed-0a8c6b7cbba5%2Fimage.png