Proyek Akhir: Aplikasi Daftar Tugas

Menggabungkan semua materi: komponen, props, emits, v-model, v-for, computed, filter, dan state reaktif untuk membangun aplikasi Daftar Tugas lengkap. Ditutup dengan build, deploy, dan langkah belajar berikutnya.

Part 25 dari 25 ± 75 menit Gratis

Saatnya merangkai semuanya

Di bab terakhir kita membangun aplikasi Daftar Tugas (To-Do). Kelihatannya sederhana, tetapi di dalamnya terpakai hampir seluruh konsep inti Vue — dan inilah bentuk "kerangka" banyak aplikasi nyata (tambah, ubah, hapus, filter data).

Fitur yang akan dibuat

  • Menambah tugas lewat form (dengan v-model dan @submit.prevent); tugas kosong ditolak.
  • Menandai tugas selesai dengan checkbox.
  • Menghapus tugas.
  • Filter: Semua / Aktif / Selesai.
  • Penghitung tugas yang belum selesai.
  • Pesan "belum ada tugas" saat daftar kosong.

Merancang sebelum menulis

Selalu mulai dari data, baru tampilan:

// bentuk data satu tugas
{ id: 1, judul: 'Belajar Vue', selesai: false }

// state di App.vue
const daftar = ref([])             // semua tugas
const input = ref('')              // isi kolom form
const filter = ref('semua')        // 'semua' | 'aktif' | 'selesai'

Lalu tentukan pembagian komponen:

KomponenTanggung jawabKomunikasi
App.vueMemegang state, logika tambah/hapus/filterMemberi props, mendengar event
ItemTugas.vueMenampilkan satu tugasProp tugas; emit toggle & hapus

Langkah demi langkah

1. Form tambah.

<form id="form" @submit.prevent="tambah">
  <input id="input" v-model="input" placeholder="Tugas baru...">
  <button>Tambah</button>
</form>

function tambah() {
  const judul = input.value.trim()
  if (!judul) return                 // tolak kosong / spasi saja
  daftar.value.push({ id: Date.now(), judul, selesai: false })
  input.value = ''
}

2. Computed turunan. Daftar yang ditampilkan dan jumlah sisa tidak disimpan terpisah — dihitung:

const tampil = computed(() => {
  if (filter.value === 'aktif') return daftar.value.filter(t => !t.selesai)
  if (filter.value === 'selesai') return daftar.value.filter(t => t.selesai)
  return daftar.value
})
const sisa = computed(() => daftar.value.filter(t => !t.selesai).length)

3. Komponen item. Anak tidak mengubah data sendiri; ia hanya melapor.

<!-- ItemTugas.vue -->
<template>
  <li class="tugas" :class="{ selesai: tugas.selesai }">
    <input type="checkbox" class="cek" :checked="tugas.selesai" @change="emit('toggle', tugas.id)">
    <span>{{ tugas.judul }}</span>
    <button class="hapus" @click="emit('hapus', tugas.id)">x</button>
  </li>
</template>
<script setup>
defineProps({ tugas: { type: Object, required: true } })
const emit = defineEmits(['toggle', 'hapus'])
</script>

4. Merangkai di induk.

<ul>
  <ItemTugas v-for="t in tampil" :key="t.id" :tugas="t" @toggle="toggle" @hapus="hapus" />
</ul>
<p class="kosong" v-if="tampil.length === 0">Belum ada tugas.</p>

function toggle(id) { const t = daftar.value.find(x => x.id === id); if (t) t.selesai = !t.selesai }
function hapus(id) { daftar.value = daftar.value.filter(x => x.id !== id) }

Pengembangan lanjutan (coba sendiri)

  • Simpan ke localStorage dengan watch(daftar, ..., { deep: true }) dan muat di onMounted.
  • Edit judul tugas dengan klik dua kali (@dblclick).
  • Pindahkan state ke Pinia dan tambahkan animasi TransitionGroup.
  • Sambungkan ke API sungguhan memakai pola loading/error (bab 23).

Dari latihan ke proyek nyata: build & deploy

npm run build           # menghasilkan folder dist/ (HTML, CSS, JS yang sudah dikecilkan)
npm run preview         # mencoba hasil build secara lokal
  • Hosting statis (Netlify, Vercel, Cloudflare Pages, GitHub Pages): unggah isi dist/. Untuk mode createWebHistory tambahkan aturan fallback ke index.html.
  • Server sendiri (Nginx): arahkan root ke dist/ dan tambahkan try_files $uri /index.html;.
  • Variabel lingkungan: nama harus berawalan VITE_ (mis. VITE_API_URL), dibaca lewat import.meta.env.VITE_API_URL.
  • Testing: Vitest + @vue/test-utils untuk komponen; Playwright/Cypress untuk uji end-to-end.

Setelah kursus ini, belajar apa?

TopikUntuk apa
TypeScript + VueKode lebih aman di proyek besar
NuxtFramework fullstack Vue: SSR/SEO, routing otomatis
VueUseRatusan composable siap pakai
UI library (Vuetify, PrimeVue, Naive UI, Element Plus)Komponen siap pakai
Vitest & PlaywrightPengujian

🎉 Selamat! Menyelesaikan bab ini berarti kamu menguasai fondasi Vue 3 — dari template syntax sampai state management. Selesaikan kuis akhir untuk meraih sertifikat, lalu bangun proyek pribadimu sendiri.

Praktikkan langsung, gratis

Tulis dan jalankan kode langsung di browser, dapatkan penilaian otomatis. Daftar gratis kapan saja untuk menyimpan progres dan meraih sertifikat.

Coba latihan sekarang, tanpa daftar
Bagikan: WhatsApp Facebook LinkedIn X