【问题标题】:Vuejs synchronously request before render dataVuejs 在渲染数据之前同步请求
【发布时间】:2016-10-10 13:51:16
【问题描述】:

我有需要身份验证的单页应用程序。当用户通过身份验证然后访问某些页面或点击浏览器中的重新加载按钮时,它将请求提供其身份验证数据的 api。然后我有一个这样的错误:

[Vue warn]: Error when evaluating expression "auth.name": TypeError: Cannot read property 'name' of null (found in component: <navbar>)

这个错误是因为 vue 渲染 auth data 而对 api 的请求还没有完成。

是否可以让 vue 在渲染 auth data 之前先等待请求 api 完成?

更清楚这里发生了什么。代码如下:

// main.js
import Vue from 'vue'
import App from './App.vue' // root vue
import store from './vuex/store' // vuex
import router from './router' // my router map

sync(store, router)
router.start(App, '#app')
// end main.js



// App.vue
<template>
  <main>
    <div class="wrapper">
      <router-view></router-view>
    </div>
  </main>
</template>

<script>
  import authService from './services/auth' // import authservice

  ready () {
    // here is code that should be done first before vue render all authData
    auth.getUser((response) => {
      self.authData = response
    })
  },
  data () {
    return {
      authData: null // default is null until the api finish the process
    }
  }
</script>
// end App.vue



// SomeRouterComponents.vue
<template>
  <!-- some content -->
  <div>
    // always got error: cannot read property 'name' of null
    // here I expect to render this after api has been resolved
    {{ $root.authData.name }}
  </div>
  <!-- some content -->
</template>

【问题讨论】:

  • 您应该发布您的代码。我认为没有必要同步
  • @YerkoPalma 我正在使用 vue-router 和 vuex。目前我将代码(用于请求 api)放在 App.vue 中的 ready()
  • @YerkoPalma 我的代码就像一般的单页应用程序项目,直到我遇到这个问题。
  • 更新我的问题

标签: javascript vue.js synchronous vue-resource


【解决方案1】:

您可以在启用waitForData选项的情况下使用data transition hook:

<script>
  import authService from './services/auth'

  export default {
    route: {
      waitForData: true, // wait until data is loaded

      data (transition) {
        authService.getUser((response) => {
          transition.next({ authData: response }) // set data
        })
      }
    },

    data () {
      return {
        authData: null
      }
    }
  }
</script>

另外,如果您不想使用该选项,可以使用 $loadingRouteData 属性检查数据是否已加载。

更多细节在这里: http://router.vuejs.org/en/pipeline/data.html

【讨论】:

    【解决方案2】:

    您可以阻止 Vue 尝试访问对象属性,如下所示:

    {{ $root.authData ? $root.authData.name : null }}
    

    在某些情况下,您甚至可以将 null 更改为 Loading... 消息。

    【讨论】:

      【解决方案3】:

      如您所说的问题是您尝试访问一个不存在的对象,并且由于该错误,Vue 无法在下一个滴答中呈现它。解决方案是使用简单的v-if 来检查数据是否加载,这仅适用于响应式数据。

      根组件

        import auth from './services/auth' // import authservice
      
        ready () {
          // here is code that should be done first before vue render all authData
          auth.getUser((response) => {
            self.authData = response
            self.dataReady = true
          })
        },
        data () {
          return {
            authData: null, // default is null until the api finish the process
            dataReady: false
          }
        }
      

      其他组件

        <div v-if="dataReady">
          // note that if you use v-show you will get the same error
          {{ $root.authData.name }}
        </div>
        <div v-if="!dataReady">
          // or some other loading effect
          Loading...
        </div>
      

      我使用 v-if="!dataReady" 而不是 v-else,因为它将在 Vue 2.0 中被弃用

      【讨论】:

      • 另外,尝试使用另一个循环钩子而不是 ready,因为当 DOM 被渲染时调用 ready ,并且您希望该代码在该事件之前。首选created钩子
      • 如果我在 main.js 中调用 authService 怎么样。喜欢:auth.getUser(null, (response) =&gt; { router.start(App, '#app') }) 然后在 App.vue 中使用:this.authData = auth.user 接收身份验证数据我只是尝试这个并按预期工作。但我不确定这是否是一个好的解决方案
      • 因为如果我使用您提供的解决方案。每个 routerComponent 中都会有很多 v-if="dataReady"。
      猜你喜欢
      • 2021-01-11
      • 2019-12-31
      • 2019-01-11
      • 1970-01-01
      • 1970-01-01
      • 2016-08-02
      • 2021-01-31
      • 2017-02-02
      • 2021-01-04
      相关资源
      最近更新 更多