【问题标题】:Vue / Router: How do I correctly fetch data before rendering page content?Vue / Router:如何在渲染页面内容之前正确获取数据?
【发布时间】:2020-05-30 06:16:45
【问题描述】:

我将 Nuxt 与 Vue 路由器和 Axios 一起使用。我看到 Vue Router 有一个很棒的功能,叫做Navigation Guards

不幸的是,在下面的示例中,我的beforeRouteEnter() 函数被调用,但似乎在fetchPageData(next) 中调用我的手动next() 方法之前退出并切换页面。

这里的正确模式是什么?

export default {
    beforeRouteEnter (to, from, next) {
        next(vm => {
            vm.fetchPageData(next);
        });
    },
    methods: {
        async fetchPageData(next) {
            const result = await this.$axios.$get('/api/v2/inventory/3906?apiKey=f54761e0-673e-4baf-86c1-0b85a6c8c118');
            this.$store.commit('property/setProperty', result[0]);
            next();
        }
    }
}

我假设我对next(vm => {}) 的第一次调用是异步运行的,允许继续执行,导致在我(很可能是错误地)尝试回调 next() 之前发生页面更改。

【问题讨论】:

    标签: javascript vue.js vue-router nuxt.js


    【解决方案1】:

    你是对的,第二次调用next() 是不正确的。您对next() 的第一次调用告诉路由器“继续,您可以继续更改活动组件(创建/安装/渲染),当组件创建时,调用我的回调(作为参数传递给next()

    您可以按照Data fetching - fetching before navigation Docs 中的指导进行操作,即。先获取数据,然后调用next(),但这需要从组件本身提取获取逻辑。

    一般来说,我发现以假设数据在第一次渲染时不在这里并且稍后所有异步调用解析时出现的方式编写所有组件更容易......

    更新 Nuxt 异步数据获取选项

    当您使用 Nuxt.js 时,您还有其他一些如何使用异步数据的选项:

    1. nuxtServerInit - 用于使用来自服务器端的数据填充客户端 Vuex 存储
    2. fetch method - fetch 方法用于在渲染页面之前填充存储。它类似于asyncData 方法,只是它不设置组件数据并允许您将数据放入存储中。从fetch 方法返回 Promise 将使 Nuxt 在渲染组件之前等待 Promise 解决...
    3. asyncData 方法可用于获取数据并将其放入组件的data 中。从asyncData 方法返回 Promise 将使 Nuxt 在渲染组件之前等待 Promise 解决...
    export default {
      async fetch({store, $axios}) {
        const result = await $axios.$get('/api/v2/inventory/3906');
        store.commit('property/setProperty', result[0]);
      }
    }
    

    【讨论】:

    • 遗憾的是,asyncData 对我不起作用,因为我需要将数据放入存储中,但我似乎无法从其中访问存储。您能否发布一个示例,说明如何将 next() 与您提到的“从组件本身提取获取逻辑”一起使用。
    • 添加了更多关于如何处理异步数据的 Nuxt 特定选项。如果您使用的是商店,请使用 fetch 而不是 asyncData....
    【解决方案2】:

    那里发生了什么,你已经打电话给next,那是 为什么路线会立即进入。

    你接下来要打电话到哪里?

    beforeRouteEnter (to, from, next) {
        next(vm => {  // <= HERE you execute next
            vm.fetchPageData(next);
        });
    },
    

    并且上面的代码会在组件已经渲染好的时候执行vm.fetchPageData

    因此,即使您不在fetchPageData 上调用next,路由也会进入。


    假设您想在 BE 获取某些数据后进入视图,您可以在路由器配置上使用 beforeEnter

    const router = new VueRouter({
      routes: [
        {
          path: '/foo',
          component: Foo,
          beforeEnter: (to, from, next) => {
            axios.get('api/...')
              .then(response => {
                 store.commit('mutation', response)
                 next()
              })
              .catch(e => {
                alert('Something went wrong')
                next(false)
              })
          }
        }
      ]
    })
    

    另一种解决方案是允许路径进入,但在获取数据时显示加载器:Checkout this answer

    【讨论】:

    • 您能否建议一种方法来实现我的目标(首先加载数据,然后切换页面)从组件内部(从可读性角度 - 而不是在路由器配置中)?我不确定如何在不使用 next 函数的情况下访问 vm(以访问 $axios),然后过早调用。
    • 据我所知,您正在使用 axios 实例。因此,您可以导入此实例并在路由器配置中使用 axios。在这种情况下,您将不需要使用 this(Vue 实例)
    • 如果您仍然找不到解决方案,请联系我 rolanddoda2014@gmail.com,我将为您制作一个简单的演示
    最近更新 更多