iT邦幫忙

2023 iThome 鐵人賽

DAY 15
0
Vue.js

Nuxt 3 初學者指南:30天從基礎到實踐系列 第 15

Day 15 – Nuxt 3 Data fetching

  • 分享至 

  • xImage
  •  

Nuxt 3 提供兩個 composables(useFetchuseAsyncData)和一個 utils($fetch) 做為取得資料函式:

  • useFetch 最簡單最常用的函式
  • $fetch 能根據使用者的行為發出請求
  • useAsyncData$fetch 一起使用,有更多的設定可以使用

useFetch

useFetch 測試昨天寫的 API。

使用方式

Step 1

app.vue 加入以下程式碼。

// app.vue
<template>
  <div>
    <div v-for="item in list.data">
      {{ item.key.replaceAll('todo:', '') }}
      <input type="checkbox" v-model="item.value.isFinish" @change="Put(item)">
      <button type="button" @click="Delete(item)">Delete</button>
    </div>
  </div>
  
  <label for="todo">todo:</label>
  <input type="text" id="todo" name="todo" v-model="todo" />
  <button type="button" @click="Post">Submit</button>
</template>

<script setup lang="ts">
  const todo = ref('')
  const list = ref([])

  list.value = await useFetch('/api/todo')
  const Post = async () => {
    await useFetch('/api/todo', {
      method: 'post',
      body: { name: todo.value }
    })
    list.value = await useFetch('/api/todo')
  }

  const Put = async (item) => {
    await useFetch('/api/todo', {
      method: 'put',
      body: { name: item.key.replaceAll('todo:', ''), isFinish:item.value.isFinish }
    })
    list.value = await useFetch('/api/todo')
  }

  const Delete = async (item) => {
    await useFetch('/api/todo', {
      method: 'delete',
      body: { name: item.key.replaceAll('todo:', '')}
    })
    list.value = await useFetch('/api/todo')
  }
</script>

Step 2

畫面顯示:

https://ithelp.ithome.com.tw/upload/images/20230929/201628050kf33Mm36T.png

Step 3

測試功能:

新增

https://ithelp.ithome.com.tw/upload/images/20230929/20162805xk6fbm4Lb4.png

https://ithelp.ithome.com.tw/upload/images/20230929/20162805YOTyzfyFVn.png

修改

https://ithelp.ithome.com.tw/upload/images/20230929/20162805U3xviCe1rW.png

刪除

https://ithelp.ithome.com.tw/upload/images/20230929/201628050laQXTlUXc.png

https://ithelp.ithome.com.tw/upload/images/20230929/20162805XKGVsLtyvX.png

https://ithelp.ithome.com.tw/upload/images/20230929/20162805EbgHTkxI60.png

其他設定

useFetch 有提供一些設定透過參數可以控制其行為。

Lazy

預設情況下,useFetch 在使用 Vue Suspense 導覽至新頁面前會等待其非同步函式解析,如果使用 lazy 選項就會忽略此功能。

<template>
  <div v-if="pending">
    ...
  </div>
  <div v-else>
    <div v-for="item in list">
      ...
    </div>
  </div>
</template>

<script setup lang="ts">
const { pending, data: list } = useFetch('/api/todo', {
  lazy: true
})
</script>

也可以使用 useLazyFetch

const { pending, data: list } = useLazyFetch('/api/todo')

Client-only

預設情況下,useFetch 會在客戶端和伺服器環境上執行,將 server 設為 false 可以只在客戶端執行。
lazy 一起用對於第一次渲染時不需要的資料非常有用。

const { pending, data: list } = useFetch('/api/todo', {
  lazy: true,
  server: false
})

Refresh

如果想要手動更新資料可以使用 refresh

<template>
  <div>
    ...
    <button @click="refresh">Refresh data</button>
  </div>
</template>

<script setup lang="ts">
const { data:list, error, execute, refresh } = await useFetch('/api/todo')
</script>

Watch

如果想要監聽某個值並更新資料可以使用 watch,可以監聽一個或多個元素。

const id = ref(1)

const { data:list, error, refresh } = await useFetch('/api/todo', {
  watch: [id]
})

$fetch & useAsyncData

$fetch 是 Nuxt 3 提供用來獲取資料的 Utils,讓我們不需要額外安裝套件即可進行 HTTP 請求。

在元件中直接使用 $fetch 會導致重複取得資料(SSR 時在伺服器端取得一次、Hydration 時再次取得),因為 $fetch 不會將狀態從伺服器傳遞到客戶端。

...
// 這邊會執行兩次
list.value = await $fetch('/api/todo')
...  

為了避免在元件中重複取得資料的問題,官方文件明確建議使用 useFetchuseAsyncData + $fetch,這樣可以確保資料在伺服器端取得後能傳遞到客戶端。

...
list.value = await useAsyncData('todo', () => $fetch('/api/todo'))
...

也可以在客戶端的事件裡直接使用 fetch

// app.vue
<template>
...
  <button type="button" @click="Post">Submit</button>
</template>

<script setup lang="ts">
...
  const Post = async () => {
    await $fetch('/api/todo', {
      method: 'post',
      body: { name: todo.value }
    })
  }
...
</script>

結論

以開發的角度來說使用 useFetch 較為方便,不管什麼情況 useFetch 都有相對應的設定,反而 $fetchuseAsyncData 在使用上有許多要注意的地方,一不小心可能就會踩到雷。

🌞 Upcoming

這幾天介紹了 Server API 的使用方式及取得資料的方法,明天會介紹用於轉場的效果 Transitions


參考資料:

Data fetching
useFetch
useAsyncData
fetch


上一篇
Day 14 – Nuxt 3 Server RESTful API
下一篇
Day 16 – Nuxt 3 Transitions
系列文
Nuxt 3 初學者指南:30天從基礎到實踐30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言