Nuxt.js Fundamental ตอนที่ 6 - การ Fetch ข้อมูลจาก API

เนื้อหาของบทเรียน Nuxt.js
- ตอนที่ 1 - Getting Started with Nuxt.js
- ตอนที่ 2 - สร้าง Nuxt.js ด้วย create-nuxt-app
- ตอนที่ 3 - การกำหนด Routing
- ตอนที่ 4 - Nuxt.js Concept
- ตอนที่ 5 - Nuxt Content และ Async Data
- ตอนที่ 6 - การดึงข้อมูลจาก APIs
- ตอนที่ 7 - การใช้งานร่วมกับ Vuex Store
- ตอนที่ 8 - ทำระบบ Authentication ด้วย Nuxt.js
- ตอนที่ 9 - การ Deploy Nuxt.js
- ตอนที่ 10 - การทำ Internal API และ Middleware
- ตอนที่ 11 - ทำ SEO และ Meta tags
- ตอนที่ 12 - Workshop
ต่อมาคือการ Fetch ข้อมูลจาก API นะครับ ใน Vue.js ปกติ เราอาจจะ fetch data โดยผ่าน function mounted()
หรือสร้าง function ใน methods
อาจจะใช้ fetch
หรือ axios
ก็ได้
ซึ่งใน Nuxt ผมจะยกตัวอย่างการใช้ axios นะครับ โดยเราสามารถ install ได้แบบปกติเลย
npm install axios
แต่ตัว Nuxt ก็มี Nuxt Axios ที่มีข้อดีคือ
- Set ตัว baseUrl ให้เรา
- ง่ายต่อการ
setToken
หรือทำ authentication - inject เป็น global ทำให้เรียกใช้งานได้ง่าย ไม่ต้อง import ทุกครั้ง
- กำหนด retry เพื่อ request อีกรอบกรณี error / failed
- ใช้ fetch แบบ isomorphic HTTP requests (fetch ทั้ง Server side และ client side)
วิธีใช้งาน ก็คล้ายๆ Nuxt Content ครับ คือ install ก่อน
npm install @nuxtjs/axios
จากนั้นไปเพิ่ม module ใน nuxt.config.js
module.exports = { modules: ['@nuxtjs/axios'],
axios: {}}
และกำหนด options ผ่าน object axios
ถ้าเรามี environment variable API_URL
มันจะ override ค่า baseURL
นะครับ
ซึ่งรูปแบบการใช้ fetch
หรือ axios
ก็เหมือนกับการ request api แบบปกติที่เขียนด้วย Vue.js เลยครับ
การใช้ fetch
fetch(url) .then((response) => response.json()) .then((data) => console.log(data))
การใช้ axios
axios.get(url).then((response) => console.log(response.data))
ใน axios ปกติ เวลาเราได้ข้อมูล response เราต้องดึงข้อมูลจาก response.data
ใช่มั้ยครับ แต่ถ้าเราใช้ Nuxt Axios มันจะมี shortcut เราสามารถใช้ได้เลยเช่น $get()
// แบบ axios ปกติaxios.get(url).then((res) => res.data)
// แบบ Nuxt Axios shortcut ($)axios.$get(url).then((res) => console.log(res))
Fetching Data ด้วย asyncData
มาลองดึงข้อมูล API กันดีกว่า โดยผมจะใช้เว็บ https://picsum.photos/ เป็น API นะครับ เป็น API ที่ไว้สำหรับดึงข้อมูลรูปภาพ
- โดยใช้
/v2/list
- เพื่อดึง photos แบบ list - และ
/id/{id}/info
- สำหรับรายละเอียดของรูปครับ
ผมสร้างไฟล์ pages/photos/index.vue
ขึ้นมา
<template> <div class="container"> <h1>Photos</h1> <div class="photos"> <nuxt-link v-for="photo in photos" :to="{ path: `/photos/${photo.id}` }" :key="photo.id"> <img :src="photo.download_url" class="photo-item" /> {{ photo.author }} </nuxt-link> </div> </div></template><script> export default { head() { return { title: 'Nuxt Fetch API' } }, async asyncData({ $axios }) { const photos = await $axios.$get('https://picsum.photos/v2/list?limit=12') return { photos } } }</script><style scoped> .container { padding: 1em; width: 1220px; margin: 0 auto; } .photos { display: grid; grid-template-columns: 1fr 1fr 1fr 1fr; grid-template-rows: auto; grid-gap: 1em; text-align: center; }
.photo-item { width: 100%; height: 256px; object-fit: cover; }</style>
จากโค๊ดด้านบน หน้า /photos
จะดึงข้อมูลรูปแบบ list มาแสดงผล และใช้ <nuxt-link>
กำหนด ตาม photo.id
เพื่อ link ไป dynamic route ของเรานั่นเอง
<nuxt-link v-for="photo in photos" :to="{ path: `/photos/${photo.id}` }" :key="photo.id">
โดย <nuxt-link>
เราใช้ :to
โดยส่ง object {path: '/url'}
ไป เช่น /photos/1
, /photos/2
ต่อมา เราจะกำหนด dynamic routing สำหรับแต่ละรูป โดยสร้างไฟล์ pages/photos/_id.vue
ขึ้นมา และทำการรับ route.params
จากนั้น ก็ fetch api โดยใช้ asyncData
แบบนี้ครับ
<template> <div class="photo-info"> <h1>Photo Detail</h1> <img :src="photo.download_url" class="img" /> <p>Author : {{ photo.author }}</p>
<nuxt-link to="/photos" class="link">Back to Photos</nuxt-link> </div></template><script> export default { async asyncData({ $axios, params }) { const photo = await $axios.$get(`https://picsum.photos/id/${params.id}/info`) return { photo } } }</script>
<style scoped> .photo-info { width: 860px; margin: 0 auto; text-align: center; } .img { width: 100%; }
.link { display: inline-block; margin-top: 2em; }</style>
เพียงเท่านี้ เราก็สามารถดึงข้อมูลจาก API ด้วยการใช้ asyncData
ได้แล้วครับ
ข้อดีของ asyncData คือ?
- มันจะถูกเรียกทุกครั้ง ก่อน page load มันจะถูกเรียก 1 ครั้งฝั่ง Server Side และทุกๆ ครั้งที่ฝั่ง Client side ตอนที่เรา navigate ด้วย
<nuxt-link>
- เหมาะสำหรับดึงข้อมูลก่อนการ render (pre-render)
- สามารถ return ได้ทั้ง
Promise
หรือใช้async/await
(ถ้า Promise จะ resolve ก่อน render component) - result ของ
asyncData
จะรวมกับdata()
อัตโนมัติ ทำให้เราไม่ต้องกำหนด functiondata()
เราเข้าถึงค่าในtemplate
ได้เลย - เราสามารถกำหนดเงื่อนไขได้ ถ้า
asyncData
ถุกเรียกตอน Server side ให้ทำอะไร ถ้าเรียกตอนฝั่ง client side ให้ทำอะไร เป็นต้น - เข้าถึง dynamic route ได้ ตามตัวอย่าง ที่แสดงรูป photo info เพราะ
asyncData
เข้าถึงcontext
ได้ และในcontext
ก็มีparams
นั่นเอง
อ่าน
asyncData
เพิ่มเติมได้ที่ NuxtJS - Async Data
Hints & Questions?
เพื่อนๆลองประยุกต์ใช้ asyncData
กันดูนะครับ
- เช่น ให้มัน fetch ทุกๆ ครั้งที่ query เปลี่ยน ด้วย
watchQuery
fetch()
กับasyncData
ต่างกันยังไงนะ?- เราอยากให้หน้าแรก
/photos
fetch ครั้งเดียวพอ ตอน build time ได้มั้ย? ไม่อยากให้ fetch api ทุกครั้ง ตอน navigate ระหว่าง<nuxt-link>
อ่านบทถัดไป 👉 ตอนที่ 7 - การใช้งานร่วมกับ Vuex Store
- Authors
-
Chai Phonbopit
เป็น Web Dev ในบริษัทแห่งหนึ่ง ทำงานมา 10 ปีกว่าๆ ด้วยภาษาและเทคโนโลยี เช่น JavaScript, Node.js, React, Vue และปัจจุบันกำลังสนใจในเรื่องของ Blockchain และ Crypto กำลังหัดเรียนภาษา Rust