반응형 상태·computed·폼·목록 전이를 업무형 화면으로 통합합니다.
원본 tasks를 ref로 소유하고 완료 개수는 computed로 계산합니다. 입력 검증과 추가·완료 사건을 함수로 분리합니다.
API를 연결할 때 중복 제출, 실패 복구, 서버 검증과 낙관적 업데이트 정책을 정합니다.
컴포넌트가 커지면 Form, TaskList와 composable/store 경계로 나누고 각 계약을 테스트합니다.
완료 개수를 별도 ref로 함께 수정하면 tasks와 쉽게 불일치합니다.
로컬 프로젝트에서 확인해보세요삭제와 전체·진행·완료 필터를 추가하세요.
<script setup>
import { ref, computed } from "vue";
const title = ref(""),
tasks = ref([{ id: "1", title: "Vue 복습", done: false }]);
const completed = computed(() => tasks.value.filter((t) => t.done).length);
function add() {
const value = title.value.trim();
if (!value) return;
tasks.value.push({ id: crypto.randomUUID(), title: value, done: false });
title.value = "";
}
</script>
<template>
<main>
<h1>학습 업무</h1>
<form @submit.prevent="add">
<input v-model="title" aria-label="새 업무" /><button>추가</button>
</form>
<ul>
<li v-for="task in tasks" :key="task.id">
<label><input v-model="task.done" type="checkbox" />{{ task.title }}</label>
</li>
</ul>
<p>완료 {{ completed }}/{{ tasks.length }}</p>
</main>
</template>