NuxtJS的AsyncData和Fetch使用详解

asyncData 简介

asyncData 可以用来在客户端加载 Data 数据之前对其做一些处理,也可以在此发起异步请求,提前设置数据,这样在客户端加载页面的时候,就会直接加载提前渲染好并带有数据的 DOM,完成服务端渲染,有助于搜索引擎的抓取。
注意事项:
  1. 由于在客户端创建实例化之前加载,所以不能使用 this,钩子提供一个参数,可以获取上下文对象({isDev, route, store, env, params, query, req, res, redirect, error}等),从而做一些简单操作。
  2. 只能在路由页面组件中使用(每次加载页面都会调用),在自定义组件中无效。
  3. 返回的数据最终将与 data 数据合并,为了保证不发生页面渲染错误,返回的键应事先在 data 里声明好(如果 template 中没有使用所需属性,则并不必声明)。
  4. 钩子在路由转换期间解析,所以在 return 之前会一直等待内部逻辑处理,阻止页面加载。如果要抛出异常,可以使用参数提供的 error 方法。
使用 (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; }

  • 组合式 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 数据。
【NuxtJS的AsyncData和Fetch使用详解】注:由于 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 获取加载状态。
生命周期示意图 NuxtJS的AsyncData和Fetch使用详解
文章图片

    推荐阅读