Vue · Bab 4
Mengambil Data dengan axios
Mengambil data dari REST API dengan instance axios, menampilkan empat keadaan (memuat, galat, kosong, berhasil), mengirim parameter pencarian, dan membuat paginasi dari meta respons.
Sampai bab 3, data aplikasi tertulis langsung di kode. Aplikasi frontend terpisah yang sesungguhnya mengambil datanya dari REST API: server menyimpan data, frontend memintanya lewat HTTP lalu menampilkannya. Bab ini menyambungkan Vue ke API dengan axios, dan menangani hal yang selalu terjadi di jaringan nyata: data butuh waktu untuk datang, kadang gagal, kadang kosong.
Prasyarat: bab JavaScript 6 “JSON & fetch”. Kamu sudah tahu apa itu request, respons, dan JSON.
4.1 Dari fetch ke axios
Di bab JavaScript 6 kamu memakai fetch. Ingat dua kebiasaannya: respons harus diurai dengan res.json(), dan fetch tidak menolak janji untuk status 404 atau 500. Kamu sendiri yang harus memeriksa res.ok.
// fetch: dua langkah, dan 404 tetap dianggap "berhasil"
const res = await fetch('http://127.0.0.1:8000/api/buku/99');
if (!res.ok) {
console.log('Gagal, status', res.status);
} else {
const isi = await res.json();
console.log(isi.data.judul);
}
axios merapikan keduanya: JSON diurai otomatis ke r.data, dan status di luar 2xx melempar galat yang bisa ditangkap try/catch. Contoh fetch di atas sengaja bukan playground: di preview Vue, fetch diblokir. Semua request playground dan lab berjalan lewat axios ke server tiruan.
4.2 Satu Instance: axios.create
Daripada menulis alamat server di setiap request, buat satu instance dengan konfigurasi bersama:
const http = axios.create({
baseURL: 'http://127.0.0.1:8000/api',
headers: { Accept: 'application/json' },
});
// http.get('/buku') → GET http://127.0.0.1:8000/api/buku
baseURLditulis sekali. Saat alamat server berubah (misalnya dari laptopmu ke hosting), cukup satu baris yang diganti.- Header
Accept: application/jsonmemberi tahu Laravel bahwa klien ini ingin JSON. Tanpa header itu, galat validasi Laravel bisa berupa redirect ke halaman HTML, bukan JSON yang bisa dibaca kode.
4.3 Mengambil Data Saat Komponen Dipasang
Data diambil sekali ketika aplikasi mulai tampil, di dalam onMounted. Request butuh waktu, jadi fungsinya async dan hasilnya ditunggu dengan await. Server tiruan sengaja menunda jawaban 0,4 detik agar keadaan “memuat” terlihat.
🧪 Coba ubah: ganti r.data.data menjadi r.data dan lihat apa yang tampil. Respons API Laravel membungkus daftar di dalam data, di sampingnya ada meta dan links.
Belum ada output.
4.4 Empat Keadaan
Setiap tampilan yang bergantung pada API punya empat keadaan, dan pengguna harus tahu sedang di keadaan mana:
| Keadaan | Kapan | Yang tampil |
|---|---|---|
| memuat | request belum selesai | teks “Memuat…” dengan aria-live="polite" |
| galat | jaringan putus atau server galat | pesan untuk orang awam dengan role="alert" |
| kosong | berhasil, tetapi daftar kosong | “Tidak ada buku yang cocok” |
| berhasil | ada data | daftar |
Urutan v-if / v-else-if penting: tanpa keadaan galat, server mati terlihat seperti “tidak ada buku”, padahal bukunya ada. Playground ini sengaja memakai port yang salah (9999) sehingga jaringan gagal:
🧪 Coba ubah: kembalikan port ke 8000 lalu Jalankan; keadaan berhasil tampil. Lalu minta '/buku?cari=zzz' untuk melihat keadaan kosong.
Belum ada output.
Galat jaringan tidak punya respons (e.response kosong, e.code bernilai ERR_NETWORK). Galat dari server punya respons: http.get('/buku/99') melempar galat dengan e.response.status 404. Bab 5 menyatukan semua kasus itu menjadi satu fungsi.
4.5 Parameter: Cari dan Halaman
Query string tidak perlu dirangkai sendiri. Opsi params mengubah objek menjadi ?cari=…&page=… dan meng-encode karakter khusus:
http.get('/buku', { params: { cari: kata.value || undefined, page: 2 } });
// kata kosong → GET /api/buku?page=2 (nilai undefined tidak dikirim)
Pencarian di bab 2 memakai computed di klien, karena semua data sudah ada di memori. Begitu data berhalaman, klien hanya memegang satu halaman, jadi pencarian harus dilakukan server lewat parameter.
4.6 Paginasi dari meta
Respons berhalaman Laravel membawa meta.current_page dan meta.last_page. Dua angka itu cukup untuk tombol “Sebelumnya” dan “Berikutnya” yang nonaktif di tepi:
🧪 Coba ubah: cari “nusantara” dan lihat jumlah halamannya berubah. Lalu tambahkan keadaan memuat dari 4.4 ke contoh ini.
Belum ada output.
Respons juga membawa meta.links, daftar tautan yang labelnya berisi entitas HTML seperti « Previous. Jangan merendernya dengan v-html: bab 2 sudah menunjukkan bahwa v-html membuka celah XSS. Bangun tombolmu sendiri dari current_page dan last_page.
Rangkuman
| Keadaan | Elemen | Atribut |
|---|---|---|
| memuat | <p v-if="memuat"> | aria-live="polite" |
| galat | <p v-else-if="galat"> | role="alert" |
| kosong | <p v-else-if="daftar.length === 0"> | - |
| berhasil | <ul v-else> | :key di setiap item |
- Satu instance
axios.create({ baseURL, headers: { Accept: 'application/json' } })untuk semua request. - Ambil data di
onMounteddenganasync/await;r.data.databerisi daftar,r.data.metaberisi info halaman. try/catch/finally: galat menyalakan keadaan galat,finallymematikan memuat.paramsuntuk cari dan halaman; nilaiundefinedtidak dikirim.
Berikutnya: Lab bab 4 menyambungkan katalog Smart Retail ke API tiruan: empat keadaan, pencarian server, dan paginasi.