asyncData
簡介
asyncData 可以用來在客戶端加載 Data 數據之前對其做一些處理,也可以在此發起異步請求,提前設置數據,這樣在客戶端加載頁面的時候,就會直接加載提前渲染好並帶有數據的 DOM,完成服務端渲染,有助於搜索引擎的抓取。
注意事項:
- 由於在客戶端創建實例化之前加載,所以不能使用 this,鈎子提供一個參數,可以獲取上下文對象(
{isDev, route, store, env, params, query, req, res, redirect, error}
等),從而做一些簡單操作。 - 只能在路由頁面組件中使用(每次加載頁面都會調用),在自定義組件中無效。
- 返回的數據最終將與 data 數據合並,為了保證不發生頁面渲染錯誤,返回的鍵應事先在 data 里聲明好(如果 template 中沒有使用所需屬性,則並不必聲明)。
- 鈎子在路由轉換期間解析,所以在 return 之前會一直等待內部邏輯處理,會阻滯頁面加載。如果要拋出異常,可以使用參數提供的 error 方法。
- asyncData 必須返回一個對象(
Object
),否則將導致頁面無法加載。
使用方式 (Javascript)
按照官網說明 asyncData 有三種使用方式,
使用示例:
-
返回 Promise 對象的方式
export default {
asyncData({ params }) {
return axios.get(`https://my-api/posts/${params.id}`).then(res => {
return { title: res.data.title };
});
}
};
-
使用 async/await 的方式
export default {
async asyncData({ params }) {
const { data } = await axios.get(`https://my-api/posts/${params.id}`);
return { title: data.title };
}
};
-
使用回調函數的方式(v2.12 棄用)
export default {
asyncData({ params }, callback) {
// asyncData提供兩個參數(已棄用)
axios.get(`https://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(`https://my-api/posts/${params.id}`);
return { title: data.title };
}
// Promise方式
/* asyncData({ params }) {
return axios.get(`https://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(`https://my-api/posts/${params.id}`);
return { title: data.title };
}
})
export default class PageIndex extends Vue {
title: string;
}
注: vue-property-decorator
包中的組件裝飾器只定義了Vue的常用鈎子,而AsyncData
等方法屬於Nuxt自定義的鈎子,所以需要在Component
裝飾器中傳入。也可以使用Component.registerHooks(['asyncData'])
注冊該方法,注冊之后就可以直接定義在組件類的原型方法上了。還可以直接把vue-property-decorator
包替換為nuxt-property-decorator
,里面已經自動注冊了包括Vue和Nuxt的鈎子。
-
組合式 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(
`https://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(
`https://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 獲取加載狀態。
生命周期示意圖
