如何正确使用 Nuxt 2.12 中新的 fetch() 钩子进行 SSR?

How to properly use the new fetch() hook in Nuxt 2.12 for SSR?

我将 Nuxt 更新到最新版本,因为他们引入了新的 fetch() 钩子。 在我的项目中,我正在从 Prismic 检索数据。之前,我使用的是 asyncData(),但是在导航时,需要一些时间才能呈现调用 asyncData() 的页面(这是它的工作原理)。

理想的解决方案是在该特定页面上导航,并在检索数据时显示加载动画。 新的 fetch() 挂钩似乎很合适,因为它公开了 $fetchState.pending 以检查操作的状态。

现在,代码(我正在从商店的类别中检索子类别):

        data(){
            return{
                docs: []
            }
        },

        async fetch() {
            try{
                const res = await this.$prismic.api.query(this.$prismic.predicates.at('my.category.uid', this.$route.params.sub))
                const el = res.results[0]
                const query = await this.$prismic.api.query([this.$prismic.predicates.at('document.type','sub-category'), this.$prismic.predicates.at('my.sub-category.category', el.id)], { orderings: '[my.sub-category.position, my.sub-category.title]' })
                this.docs = query.results
            }   
            catch (e) {
                console.log(e)
            }
        }

这至少在客户端有效。这对正确的 SSR 有用吗?我的意思是,在 asyncData()(调用服务器端)中,this 不可访问,data() 也不可访问。如果这是正确的解决方案,那么使用 asyncData() 而不是 fetch() 有什么意义呢?

如果您正在寻找一种方法来为您的页面组件设置加载状态,您可以将数据与 asyncData 一起使用,

        data(){
            return{
                loading: true
            }
        },

        async asyncData(context) {
            try{
                const res = await context.app.$prismic.api.query(context.app.$prismic.predicates.at('my.category.uid', context.app.$route.params.sub))
                const el = res.results[0]
                const query = await context.app.$prismic.api.query([context.app.$prismic.predicates.at('document.type','sub-category'), context.app.$prismic.predicates.at('my.sub-category.category', el.id)], { orderings: '[my.sub-category.position, my.sub-category.title]' })
                const docs = query.results
                const loading = false
                return {docs, el, loading}
            }   
            catch (e) {
                console.log(e)
            }
        }

如果您使用 prismic,(如果您没有将其注册为插件)您可以通过插件将 prismic 注入到上下文中

import prismic from 'prismic-javascript'

export default (inject) => {

    inject('prismic', prismic)
}

现在您可以在上下文中访问 $prismic。

我在处理加载状态时使用的另一种方法是使用存储模块来处理请求的状态。

plugins/loading.js

export default ({store},inject) => {
    inject('changeLoading', function(){
            store.dispatch('changeLoading')
        }
    )
}

store/index.js

export const state = () => ({
    loading: false
});

export const mutations = {
    CHANGE_LOADING(state){
        state.loading = !state.loading
    }
}

export const actions = {
    changeLoading({commit}){
        commit('CHANGE_LOADING')
    }
}

export const getters = {
    getLoading(state){
        return state.loading
    }
}

所以现在您的组件中没有本地加载状态,您可以在您的商店中有一个可以更改和获取的集中状态。

        data(){
            return{
                loading: this.$store.getters['getLoading']
            }
        },

        async asyncData(context) {
            try{
                context.app.$changeLoading()
                const prismicData = await context.app.$prismic(...)
                context.app.$changeLoading()
                return {prismicData}
            }   
            catch (e) {
                context.app.$changeLoading()
                console.log(e)
            }
        }

就SSR而言,fetch的使用方式与asyncData的使用方式相同(虽然页面转换时间有所不同)。

fetchasyncData的区别:

  • asyncData 无法访问 this,而 fetch(在 Nuxt >= 2.12 中)可以。
  • asyncData的return值设置组件的数据,而fetch的return值不设置,因为fetch已经有访问权限this,所以它可以直接设置 data 道具。
  • fetch由两个optionsfetchOnServerfetchDelay)控制,而asyncData没有选项。当fetchOnServer(默认true)设置为false时,fetch钩子只在客户端调用。
  • fetch$fetchState对象耦合,提供pendingtimestamp(与fetch操作的当前状态有关);和 error 函数(允许您显示错误消息)。请注意,asyncData 在其 context 参数中还提供了 error 函数。
  • fetch 允许更快的页面转换(根据 RFC 27)。
  • asyncData仅对页面可用,而fetch可被任何组件(包括页面)使用。

除了上述差异外,这两种方法的语义是相同的。

似乎 fetchasyncData 的非正式继任者,尽管两者同时存在而没有弃用通知。由于 fetch 提供了更多功能并解决了 asyncData 的问题,我建议只使用 fetch

已解决:Nuxt 提示我一个小警告说 "node-fetch" 至少在版本 2.6.0 是必需的。出于某种原因,我的是 2.1.2.