【问题标题】:How to properly use the new fetch() hook in Nuxt 2.12 for SSR?如何在 nuxt 2.12 中为 SSR 正确使用新的 fetch() 挂钩?
【发布时间】:2020-07-16 12:02:00
【问题描述】:

我将 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() 有什么意义?

【问题讨论】:

  • 您的问题已在文档中得到解答 nuxtjs.org/api/pages-fetch fetch 在呈现路线时在服务器端调用,在导航时在客户端调用。 至少,客户端 fetchOnServer: false? 这是否适用于正确的 SSR? 是的。
  • 嗯,我确实想在服务器上获取,尤其是产品详细信息页面(用于 SEO)。我唯一的疑问是我不知道我编写的代码是否在服务器端也有效。此外,使用asyncData 的真正区别是什么?

标签: vue.js fetch nuxt.js server-side-rendering


【解决方案1】:

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

fetch和asyncData的区别:

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

除了上面的区别之外,这两种方法的语义是相同的。

似乎fetch 是asyncData 的非官方继承者,尽管两者同时存在而没有弃用通知。由于fetch 提供了更多功能并解决了asyncData 的问题,因此我建议您专门使用fetch。

【讨论】:

    【解决方案2】:

    已解决:Nuxt 提示我一个小警告,说至少需要 2.6.0 版本的“node-fetch”。由于某种原因,我的版本是 2.1.2。

    【讨论】:

      【解决方案3】:

      如果您正在寻找一种为页面组件设置加载状态的方法,您可以将数据与 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)
                  }
              }
      

      【讨论】:

      • 感谢您报告您的经验。但我想了解如何使用新的 fetch..
      • 您可以在此处阅读有关 fetch 与 asyncdata 的更多信息:stackoverflow.com/questions/49251437/…,是的,fetch 也称为服务器端,因此从 SEO 的角度来看,您很好,您还可以检查 SSR 是否适用于通过检查页面源来获取。
      • 谢谢,但他们用 2.12 版本更改了 fetch 挂钩"
      • 更改现在允许使用 this 和其他内容,如 $fetchState.pending、$fetchState.error、$fetchState.timestamp、nuxtjs.org/api/pages-fetch。还有一点就是fetch可以在所有组件中使用,而asyncData只在pages组件中使用。
      猜你喜欢
      • 2020-09-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-19
      • 2021-08-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多