NuxtJS的 AsyncData 和 Fetch 使用詳解
- 2021 年 12 月 9 日
- 筆記
- javascript, NodeJs, 前端, 後端
asyncData
簡介
asyncData 可以用來在客戶端載入 Data 數據之前對其做一些處理,也可以在此發起非同步請求,提前設置數據,這樣在客戶端載入頁面的時候,就會直接載入提前渲染好並帶有數據的 DOM,完成服務端渲染,有助於搜索引擎的抓取。
注意事項:
- 由於在客戶端創建實例化之前載入,所以不能使用 this,鉤子提供一個參數,可以獲取上下文對象({isDev, route, store, env, params, query, req, res, redirect, error}等),從而做一些簡單操作。
- 只能在路由頁面組件中使用(每次載入頁面都會調用),在自定義組件中無效。
- 返回的數據最終將與 data 數據合併,為了保證不發生頁面渲染錯誤,返回的鍵應事先在 data 里聲明好(如果 template 中沒有使用所需屬性,則並不必聲明)。
- 鉤子在路由轉換期間解析,所以在 return 之前會一直等待內部邏輯處理,阻止頁面載入。如果要拋出異常,可以使用參數提供的 error 方法。
使用方式 (Javascript)
按照官網說明 asyncData 有三種使用方式,
使用示例:
-
返回 Promise 對象的方式
export default {
asyncData({ params }) {
return axios.get(`//my-api/posts/${params.id}`).then(res => {
return { title: res.data.title };
});
}
};
-
使用 async/await 的方式
export default {
async asyncData({ params }) {
const { data } = await axios.get(`//my-api/posts/${params.id}`);
return { title: data.title };
}
};
-
使用回調函數的方式(v2.12 棄用)
export default {
asyncData({ params }, callback) {
// asyncData提供兩個參數(已棄用)
axios.get(`//my-api/posts/${params.id}`).then(res => {
callback(null, { title: res.data.title });
});
}
};
使用方式 (Typescript)
Nuxt 的 ts 版組件,有三種構建風格,
使用示例:
-
選項式 API
export default Vue.extend({
// async/await方式
async asyncData({ params }) {
const { data } = await axios.get(`//my-api/posts/${params.id}`);
return { title: data.title };
}
// Promise方式
/* asyncData({ params }) {
return axios.get(`//my-api/posts/${params.id}`).then(res => {
return { title: res.data.title }
})
}, */
});
-
類式組件
類式組件應在裝飾器內傳入該方法,而不是在 Class 內使用。
import { Component, Vue } from "vue-property-decorator";
@Component({
async asyncData({ params }) {
const { data } = await axios.get(`//my-api/posts/${params.id}`);
return { title: data.title };
}
})
export default class PageIndex extends Vue {
title: string;
}
-
組合式 API(v3.0 以上)
import { defineComponent, ref } from "@vue/composition-api";
import { useAsyncData } from "#app";
export default defineComponent({
async setup() {
const { data } = await useAsyncData("count", () => $fetch("/api/count"));
return {
title: data.title
};
}
});
fetch
簡介
舊版本的 fetch 在組件實例化之前運行,無法使用 this,如同 asyncData,提供了可查詢長下文的參數,且亦只能在頁面級組件中使用,並且只能通過上下文參數操作 store 狀態的數據,而不能設置或合併 data 數據。
註:由於 fetch 鉤子的功能在 nuxt v2.12 以上版本作了較大調整,所以下文只記錄新的使用方式。
fetch 用來在組件載入時預先提取數據,運行於組件實例創建之後(created)頁面渲染完成之前(mounted),並且可以用於任何組件(包括路由頁面或自定義組件)和隨時通過$fetch 方法主動更新數據。
使用方式
默認選項式組件:
export default {
fetchOnServer: false, //可以通過內置的fetchOnServer屬性,來關閉服務端fetch行為。
async fetch() {
const { data } = await axios.get(
`//my-api/posts/${this.$route.params.id}`
);
this.title = data.title;
}
};
Typescript 類式組件:
import { Component, Vue } from "vue-property-decorator";
@Component
export default class PageBarIndex extends Vue {
async fetch(this: PageBarIndex) {
const { data } = await axios.get(
`//my-api/posts/${this.$route.params.id}`
);
this.title = data.title;
}
}
asyncData 和 fetch 的區別
- 組件限制
- asyncData 僅限於頁面級組件。
- fetch 可用於任意組件。
- 獲取上下文
- asyncData 不可以使用 this,只能通過回調參數獲取上下文對象。
- fetch 可以使用 this。
- 數據操作
- asyncData 通過 return 合併 data 數據。
- fetch 可以使用 this 直接修改賦值。
- 調用時機
- asyncData 只在頁面創建前調用。
- fetch 在頁面實例創建後調用,並可以通過$fetch 方法隨時觸發,$fetchState.timestam 屬性可以獲取最後一次觸發的時間戳。
- 錯誤處理
- asyncData 通過 error 參數拋出錯誤,但並不會在頁面顯示異常。
- fetch 可以使用 throw new Error()來拋出異常,在頁面調用$fetchState.error 方法獲取異常狀態。
- 頁面渲染
- asyncData 在頁面創建前填充數據。
- fetch 可通過 fetchOnServer 屬性設置是否允許在服務端獲取數據,設置為 false 將可以在渲染數據時通過$fetchState.pendinding 獲取載入狀態。