템플릿 문법과 필수 디렉티브
HTML 태그 안에 마법의 주문(디렉티브)을 걸어 화면을 동적으로 조작할 수 있습니다. Vue의 디렉티브(Directive)는 모두 v- 로 시작하며, 초보자가 반드시 알아야 할 핵심 디렉티브 4가지를 그림으로 정리했습니다.
그리고 궁극의 마법, v-model (양방향 바인딩)
회원가입 폼을 만들 때 사용자가 <input>에 글씨를 입력하는 즉시, 스크립트 내부의 변수(ref) 값도 자동으로 똑같이 바뀌게 하고 싶다면 v-model 하나만 쓰면 됩니다. React처럼 value={text} onChange={...} 처럼 복잡하게 코드를 짤 필요가 전혀 없습니다.
<!-- ==========================================
// 📂 TodoList.vue (필수 디렉티브 4종 세트 실전 예제)
// ========================================== -->
<script setup>
import { ref } from 'vue';
// 입력창과 연결할 변수 (v-model 전용)
const newTodo = ref('');
// 할 일 목록 배열 (v-for 전용)
const todos = ref([
{ id: 1, text: 'Vue 3 문법 복습하기', done: false },
{ id: 2, text: '운동 다녀오기', done: true }
]);
// 할 일 추가 함수 (v-on 전용)
const addTodo = () => {
if (newTodo.value.trim() === '') return;
todos.value.push({
id: Date.now(),
text: newTodo.value,
done: false
});
newTodo.value = ''; // 입력창 비우기
};
</script>
<template>
<div class="p-8 max-w-md mx-auto bg-white rounded-xl shadow mt-10">
<h2 class="text-2xl font-bold mb-4">할 일 목록 (Todo)</h2>
<div class="flex gap-2 mb-6">
<!-- ✨ [v-model]: 입력창과 변수를 하나로 묶어버림 (양방향 연결) -->
<!-- ✨ [v-on]: @keyup.enter 로 엔터키를 쳤을 때 함수 실행 -->
<input
v-model="newTodo"
@keyup.enter="addTodo"
placeholder="할 일을 입력하세요..."
class="border p-2 rounded flex-1"
/>
<!-- ✨ [v-bind]: :disabled 로 조건에 따라 버튼 비활성화 속성 제어 -->
<button
@click="addTodo"
:disabled="newTodo.length === 0"
class="bg-blue-500 text-white px-4 rounded disabled:bg-gray-300"
>
추가
</button>
</div>
<!-- ✨ [v-if]: 목록이 텅 비어있을 때만 이 <div>를 보여줌 -->
<div v-if="todos.length === 0" class="text-gray-400 text-center py-4">
등록된 할 일이 없습니다!
</div>
<!-- ✨ [v-else]: 목록이 비어있지 않으면 <ul> 태그를 보여줌 -->
<ul v-else class="space-y-2">
<!-- ✨ [v-for]: todos 배열을 뱅글뱅글 돌면서 <li> 태그를 마구 생성함 -->
<!-- [주의] v-for를 쓸 때는 요소 구분을 위해 :key 를 반드시 넣어주세요! -->
<li
v-for="item in todos"
:key="item.id"
class="flex gap-2 items-center p-2 border rounded"
>
<input type="checkbox" v-model="item.done" />
<!-- ✨ [v-bind]: 체크 여부에 따라 취소선 클래스를 동적으로 붙임 -->
<span :class="{ 'line-through text-gray-400': item.done }">
{{ item.text }}
</span>
</li>
</ul>
</div>
</template>