조건부 렌더링(Conditional Rendering) 개념
조건부 렌더링이란,
조건에 따라 화면에 렌더링 하는 것을 말한다.
조건이 참(true)일 경우 화면에 렌더링되고 거짓(false)일 경우 렌더링 되지 않는다.
Vue에서는 v-if, v-show가 조건부 렌더링 역할을 한다.
v-if
The directive v-if is used to conditionally render a block. The block will only be rendered if the directive’s expression returns a truthy value.
- vue 공식문서 -
vue 공식문서에 따르면, "v-if는 조건에 따라 블록을 렌더링하기 위해 사용되며, true값을 반환할 때만 렌더링 된다." 소개 한다.
v-if 기본기
<template>
<div>
<p v-if="isShow">Superpil is awesome!</p>
<p v-if="isNoShow">No Show</p>
</div>
</template>
<script>
export default {
data() {
return {
isShow: true,
isNoShow: false,
};
},
};
</script>
👉 <p v-if="isShow">Superpil is awesome!</p>
- isShow가 true라서 해당 태그는 화면에 렌더링 된다.
👉 <p v-if="isNoShow">No Show</p>
- isNoShow가 false라서 해당 태그는 화면에 렌더링 되지 않는다.
v-if 와 v-else
<template>
<div>
<p v-if="isShow">Superpil is awesome!</p>
<p v-else>No Show</p>
<button @click="isShow = !isShow">변경</button>
</div>
</template>
<script>
export default {
data() {
return {
isShow: true,
};
},
};
</script>
👉 <p v-else>No Show</p>
- 만약, 해당 예제 처럼 두개의 p태그가 상호 반대작용하여 렌더링을 원한다면 v-if와 v-else를 사용하면 된다.
👉 <button @click="isShow = !isShow">변경</button>
- 버튼을 클릭하면 isShow가 true면 false로 false면 true로 변견된다.
- isShow가 true면 "Superpil is awesome!"이 false면 "No Show"가 렌더링 된다.
v-if 와 v-else-if, v-else
v-else-if는 Vue 2.1.0부터 새롭게 추가 되었다.
자바스크립트 if문의 else if문과 동일한 기능을 가지고 있으며 다수의 조건이 필요한 경우 사용한다.
<template>
<div>
<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>
</div>
</template>
<script>
export default {
data() {
return {
type: "A",
};
},
methods: {},
};
</script>
👉 <div v-else-if="type === 'B'">B</div>
- type가 B일 경우 해당 태그가 렌더링 된다.
👉 <div v-else>Not A/B/C</div>
- type이 A, B, C중 아무것도 아닌 경우 해당 태그가 렌더링 된다.
v-if 다양하게 사용하기
자바스크립트 코드 사용
<template>
<div>
<p>{{ arr.length }}</p>
<p v-if="arr.length >= 3">수량 달성!</p>
<button @click="addArr">UP</button>
</div>
</template>
<script>
export default {
data() {
return {
arr: [],
};
},
methods: {
addArr() {
this.arr.push("1");
},
},
};
</script>
👉 <button @click="addArr">UP</button>
- 버튼 클릭 시 addArr()가 실행 된다.
👉 addArr() { ... }
- 버튼 클릭 때 마다 this.arr에 1을 넣는다.
👉 <p v-if="arr.length >= 3">수량 달성!</p>
- arr길이가 3이상 일 경우 화면에 렌더링 된다.
computeds 사용
<template>
<div>
<p>{{ score }}</p>
<p v-if="checkScore">점수 달성!</p>
<button @click="score++">UP</button>
</div>
</template>
<script>
export default {
data() {
return {
score: 0,
};
},
computed: {
checkScore() {
if (this.score >= 10) {
return true;
} else {
return false;
}
},
},
};
</script>
👉 <button @click="score++">UP</button>
- 버튼을 클릭 할때 마다 score++가 실행 되어 score에 +1씩 증가한다.
👉 checkScore() { ... }
- score가 1씩 증가때 마다 checkSore()가 실행된다.
- score가 10보다 같거나 큰경우 true를 return 한다.
👉 <p v-if="checkScore">점수 달성!</p>
- true를 return 받으면 화면에 출력 한다.
v-if의 재사용
Vue tries to render elements as efficiently as possible, often re-using them instead of rendering from scratch. Beyond helping make Vue very fast, this can have some useful advantages. For example, if you allow users to toggle between multiple login types:
- Vue 공식문서 -
Vue 공식문서에 따르면 조건부 렌더링에서 Vue는 가능한 효율적으로 엘리먼트를 렌더링하기 위해 처음 엘레먼트를 새로 렌더링 하지 않고 재사용을 한다고 말한다.
<template>
<div>
<template v-if="type === 'name'">
<label>사용자 이름</label>
<input placeholder="사용자 이름을 입력하세요" />
</template>
<template v-else>
<label>이메일</label>
<input placeholder="이메일 주소를 입력하세요" />
</template>
<button @click="change">전환</button>
</div>
</template>
<script>
export default {
data() {
return {
type: "name",
};
},
methods: {
change() {
this.type === "name" ? (this.type = "email") : (this.type = "name");
},
},
};
</script>
👉 <button @click="change">전환</button>
- 버튼 클릭 시 change method가 실행 된다.
👉 change() { ... }
- type이 name일 경우 email로 email일 경우 name으로 값을 변경 한다.
👉 <template v-if="type === 'name'">
- type이 name일 경우 화면에 출력 된다.
👉 <template v-else>
- type이 name이 아닌경우 화면에 출력 된다.
👉 <input placeholder="사용자 이름을 입력하세요" />
- type이 name경우와 name이 아닌 경우 모두 input태그는 동일 하다.
- Vue는 input태그는 type이 변경될 때마다 input태그를 새롭게 렌더링 하지 않고 기존에 있는 태그를 재사용 한다.
- name input에 입력한 값이 전환 버튼을 클릭 해도 재사용되기 때문에 email input에도 여전히 남아 있다.
만약, 재사용이 아닌 별개로 사용하고 싶다면 key속성을 추가 하면 된다.
<template>
<div>
<template v-if="type === 'name'">
<label>사용자 이름</label>
<input placeholder="사용자 이름을 입력하세요" key="name" />
</template>
<template v-else>
<label>이메일</label>
<input placeholder="이메일 주소를 입력하세요" key="email" />
</template>
<button @click="change">전환</button>
</div>
</template>
<script>
export default {
data() {
return {
type: "name",
};
},
methods: {
change() {
this.type === "name" ? (this.type = "email") : (this.type = "name");
},
},
};
</script>
👉 key="name", key="email"
- key속성을 사용해서 버튼을 클릭 때 마다 input태그를 새롭게 렌더링 한다.
- 이제 name에서 입력한 값은 email로 전환 된 경우 input에 값이 사라진다.
v-show
v-if와 사용법은 거의 유사하다.
다만, v-else, v-else-if와 같은 기능은 없다.
<template>
<div>
<p v-show="isShow">v-show</p>
<button @click="isShow = !isShow">변경</button>
</div>
</template>
<script>
export default {
data() {
return {
isShow: false,
};
},
};
</script>
👉 <button @click="isShow = !isShow">변경</button>
- 버튼을 클릭하면 isShow가 true로 변경되고 p태그가 화면에 출력된다.
v-if 와 v-show 차이점
Dom에 렌더링 여부의 차이
v-if의 경우는 false상태면 Dom에 태그 자체가 렌더링 되지 않는다. 반면에 v-show의 경우 Dom에 태그가 렌더링은 되지만 display: none Css가 적용 된다.
<template>
<div>
<VueIf v-if="isOn"></VueIf>
<VueShow v-show="isOn"></VueShow>
</div>
</template>
<script>
import VueIf from "@/views/VueIf";
import VueShow from "@/views/VueShow";
export default {
components: {
VueIf,
VueShow,
},
data() {
return {
isOn: false,
};
},
};
</script>
👉 <VueShow v-show="isOn"></VueShow>
- v-show는 렌더링 결과 Dom에서 <div style="display: none;">...</div>와 같이 display: none이 적용되어 화면에서 나타나지 않는다.
👉 <VueIf v-if="isOn"></VueIf>
- v-if는 v-show와 다르게 태그 자체가 Dom에 나타나지 않고 <!——>로 나타난다.
이런 차이는 Dom태그에 렌더링 여부에만 영향을 주는 것이 아니다.
Dom에 렌더링 여부에 따라 Vue의 라이프사이클에서 영향을 준다.
아래에서 자세히 다뤄보자.
라이프사이클 훅 실행 차이
"v-if의 경우는 false상태면 Dom에 태그 자체가 렌더링 되지 않는다"고 했다.
이 말은 Dom에 부착되기 전 까지 라이프사이클이 실행되지 않는다는 의미 이다.
true가 되면 v-if는 Dom에 태크를 렌더링하고 그제서야 component의 라이프사이클 훅이 실행 된다.
반면, v-show는 v-if와 반대로 false상태라도 Dom에 이미 렌더링이 되니깐 라이프사이클이 실행된다.
다시말해 v-show는 화면에만 출력되지 않을 뿐이지 Dom에 부착되어 component의 라이프사이클 훅이 모두 실행된 상태를 의미 한다.
// index component
<template>
<div>
<VueIf v-if="isOn"></VueIf>
<VueShow v-show="isOn"></VueShow>
<button @click="isOn = !isOn">전환</button>
</div>
</template>
<script>
import VueIf from "@/views/VueIf";
import VueShow from "@/views/VueShow";
export default {
components: {
VueIf,
VueShow,
},
data() {
return {
isOn: false,
};
},
};
</script>
// VueShow component
<template>
<div>
<p>v-show Page</p>
</div>
</template>
<script>
export default {
created() {
console.log("v-show create");
},
};
</script>
// VueIf component
<template>
<div>
<p>v-if Page</p>
</div>
</template>
<script>
export default {
created() {
console.log("v-if create");
},
};
👉 console.log("v-show create")
- index componet가 화면에 렌더딩 되면 VueShow component의 created가 실행 된다.
- VueShow component가 화면에는 출력되지 않지만 라이프사이클 훅이 실행되어 console에 v-if create가 출력된다.
👉 console.log("v-if create")
- VueIf component는 Dom에 렌더링 되지 않은 상태라서 created가 실행되지 않는다.
전환버튼을 클릭하면 isOn은 true로 변경되고 VueIf, VueShow component가 화면에 출력 된다.
VueIf component는 Dom에 새롭게 렌더링 과정을 거치며, 라이프사이클 훅이 실행 된다.
따라서 console.log("v-if create")가 실행된다.
Reference
'개발노트 > Vue' 카테고리의 다른 글
[Vue] Dom접근 하기 - $ref, $refs (0) | 2021.08.09 |
---|---|
[Vue] 이벤트 전달 - Props (0) | 2021.08.08 |
[Vue] input에 숫자만 입력 가능하게 하기 (1) | 2021.08.02 |
[Vue] Naver 간편 로그인 (naverLogin_implicit-1.0.3.js) 구현 (2) | 2021.07.31 |
[Vue] Watch (0) | 2021.07.21 |
주니어 개발자의 성장 기록지
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!