Vue - 디렉티브

h.Im·2024년 9월 10일
0

Vue 기초

목록 보기
23/28
post-thumbnail

디렉티브는 v- 접두사가 있는 특수 속성입니다. 단어의 의미처럼 DOM요소에게 "~하게 작동하라" 라고 지시하는 지시문입니다.

v-if

조건부 렌더링이 필요한 경우 v-if, v-else, v-else-if, v-show를 사용할 수 있습니다.

<template>
	<h2 v-if="visible">Hello Vue3</h2>
	<h2 v-else>Bye Vue3</h2>
	<button v-on:click="toggle">토글</button>
	<hr />
	<h2 v-if="type === 'A'">A</h2>
	<h2 v-else-if="type === 'B'">B</h2>
	<h2 v-else-if="type === 'C'">C</h2>
	<h2 v-else>A, B, C가 아님</h2>
	<button v-on:click="type = 'A'">A 노출</button>
	<button v-on:click="type = 'B'">B 노출</button>
	<button v-on:click="type = 'C'">C 노출</button>
	<hr />
	<h1 v-show="ok">ok가 true일 때만 보임</h1>
	<button v-on:click="ok = !ok">토글</button>
</template>

<script>
import { ref } from 'vue'
export default {
	setup() {
		const visible = ref(true)
		const toggle = () => {
			visible.value = !visible.value
		}

		const type = ref('A')

		const ok = ref(true)

		return {
			visible,
			toggle,
			type,
			ok,
		}
	},
}
</script>

<style></style>

v-if와 v-show의 차이점

v-if는 실제로 렌더링됩니다. v-if의 값이 전환될 때마다 DOM요소를 생성하고, 전환하는 구조입니다. 반면 v-show는 우선 요소를 생성하고, CSS display:block/display:none 속성을 전환하는 방식입니다.

  • v-if: 전환 비용이 높다
  • v-show: 초기 렌더링 비용이 높다

무언가를 자주 전환해야 한다면 v-show를 사용하는게 좋고, 런타임 시 조건이 변경되지 않는다면 v-if를 사용하는 것이 더 낫습니다.


v-for

v-for 디렉티브를 사용하여 배열인 목록을 렌더링 할 수 있습니다.

<template>
	<ul>
		<li v-for="(item, index) in items" :key="item.id">
			인덱스: {{ index }} 메세지:{{ item.message }}
		</li>
	</ul>
</template>

<script>
import { reactive } from 'vue'
export default {
	setup() {
		const items = reactive([
			{ id: 1, message: 'Java' },
			{ id: 2, message: 'Html' },
			{ id: 3, message: 'Javascript' },
			{ id: 4, message: 'C++' },
		])
		return {
			items,
		}
	},
}
</script>

<style></style>

:key에 고유한 id를 부여하는 이유는 DOM 업데이트 최적화, 고유성 보장, 버그 방지 때문입니다. id를 부여하지 않으면 Vue가 업데이트해야 할 요소를 식별하지 못하고, 배열에 요소 추가 시 예상치 못한 동작이 발생할 수 있습니다. 꼭 넣어줍시다!

v-for 내부에서 선택적인 노출(아래 예시에서는 id가 짝수인 경우)을 하고자 한다면 아래와 같이 v-if를 사용할 수 있습니다.

<template>
	<ul>
		<template v-for="(item, index) in items" :key="item.id">
			<li v-if="item.id % 2 == 0">
				ID: {{ item.id }} 인덱스: {{ index }} 메세지:{{ item.message }}
			</li>
		</template>
	</ul>
</template>

<script>
import { reactive } from 'vue'
export default {
	setup() {
		const items = reactive([
			{ id: 1, message: 'Java' },
			{ id: 2, message: 'Html' },
			{ id: 3, message: 'Javascript' },
			{ id: 4, message: 'C++' },
		])
		return {
			items,
		}
	},
}
</script>

양방향 바인딩(v-model)

이전에 공부했던 개념들은 모두 reactive 데이터가 변화했을 때 화면단의 데이터가 변화한 예제들이었습니다(화면단의 이벤트 리스너로 reative 데이터가 변화하고, 화면 변화가 따라오는 흐름). 이러한 개념들을 단방향 바인딩이라고 한다면, 반대의 경우는 어떻게 처리해야 할까요?

입력 양식을 처리할 때 입력 요소의 상태와 자바스크립트의 상태를 동기화해야 하는 경우를 예제 코드로 살펴 보겠습니다.

<template>
	<h2>input Value</h2>
	<input
		type="text"
		:value="inputValue"
		@input="(event) => (inputValue = event.target.value)"
	/>
	<div>{{ inputValue }}</div>
</template>

<script>
import { ref } from 'vue'
export default {
	setup() {
		const inputValue = ref(null)
		return { inputValue }
	},
}
</script>

<style></style>

위 코드는 기존에 배문 방식으로 구현한 예시입니다. 화면단 수정 -> 이벤트 핸들러에서 반응형 데이터 수정 -> 화면에 변화 흐름을 갖습니다.

<template>
	<h2>textarea value</h2>
	<textarea v-model="textareaValue"></textarea>
	<div>{{ textareaValue }}</div>
</template>

<script>
import { ref } from 'vue'
export default {
	setup() {
		const textareaValue = ref('')
		return { textareaValue }
	},
}
</script>

v-model을 이용해 양방향 바인딩하면 코드가 굉장히 간결해짐을 볼 수 있습니다.


그 외

  • v-text : 엘리먼트의 textContent를 업데이트
<span v-text="msg"></span>
<span>{{ msg }}</span>
둘은 같은 결과
  • v-cloak : 연결된 컴포넌트 인스턴스가 컴파일을 완료할 때까지 엘리먼트에 남아있다가, 컴파일이 완료되면 사라짐.

  • v-once : 엘리먼트와 컴포넌트를 한번만 렌더링합니다. 이후에 재렌더링 할 때 엘리먼트/컴포넌트 및 모든 하위 엘리먼트는 정적 컨텐츠로 처리되고 건너 뜁니다. 업데이트 성능을 최적화하는데 사용할 수 있습니다.

<template>
	<p v-once>{{ msg }}</p>
	<p>{{ msg }}</p>
</template>

<script>
import { ref } from 'vue'
export default {
	setup() {
		const msg = ref('안녕하세용')
		return { msg }
	},
}
</script>

<style></style>

위와 같이 코드를 작성 후 msg 값을 변경하면 아래 p 태그의 텍스트만 변경됩니다.

  • v-memo : 성능과 관련된 디렉티브입니다.
<template>
	<div v-memo="[subscribers, view]">
		<p>subscribers: {{ subscribers }}</p>
		<p>view: {{ view }}</p>
		<p>likes: {{ likes }}</p>
		<button @click="subscribers++">subscribers++</button>
		<button @click="view++">view++</button>
		<button @click="likes++">likes++</button>
	</div>
</template>

<script>
import { ref } from 'vue'
export default {
	setup() {
		const subscribers = ref(4000)
		const view = ref(400)
		const likes = ref(20)
		return { subscribers, view, likes }
	},
}
</script>

<style></style>

위와 같이 v-memo를 사용할 경우, subscribers나 view 값이 변할 때만 div내 영역이 갱신되고, likes 값이 변하는 경우에는 영역이 갱신되지 않습니다. v-memo는 일반적으로 계속 사용되는 것은 아니고 성능 최적화가 필요할 때 사용합니다.

0개의 댓글