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.
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-modeldan@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:
| Komponen | Tanggung jawab | Komunikasi |
|---|---|---|
App.vue | Memegang state, logika tambah/hapus/filter | Memberi props, mendengar event |
ItemTugas.vue | Menampilkan satu tugas | Prop 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
localStoragedenganwatch(daftar, ..., { deep: true })dan muat dionMounted. - 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 modecreateWebHistorytambahkan aturan fallback keindex.html. - Server sendiri (Nginx): arahkan root ke
dist/dan tambahkantry_files $uri /index.html;. - Variabel lingkungan: nama harus berawalan
VITE_(mis.VITE_API_URL), dibaca lewatimport.meta.env.VITE_API_URL. - Testing:
Vitest+@vue/test-utilsuntuk komponen;Playwright/Cypressuntuk uji end-to-end.
Setelah kursus ini, belajar apa?
| Topik | Untuk apa |
|---|---|
| TypeScript + Vue | Kode lebih aman di proyek besar |
| Nuxt | Framework fullstack Vue: SSR/SEO, routing otomatis |
| VueUse | Ratusan composable siap pakai |
| UI library (Vuetify, PrimeVue, Naive UI, Element Plus) | Komponen siap pakai |
| Vitest & Playwright | Pengujian |
🎉 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.