首页 > 解决方案 > Vue.prototype 在页面首次加载时未定义

问题描述

所以,我试图在我的main.js文件中使用 axios 发出请求。

如图所示,我正在使用 vue-router 在加载每个组件之前发出此请求。但是,当我的网页第一次加载时,我无法让它工作。我的意思是,axios 请求是在组件加载后完成的。然后,这将失败:

mounted() {
    if (Vue.prototype.$user.role == "Owner") {
      this.isOwner = true;
      this.estancoId = Vue.prototype.$user.estanco;
    }
  },

它在控制台日志上显示了这个错误:

[Vue warn]: Error in mounted hook: "TypeError: Cannot read property 'role' of undefined"

found in

---> <Header> at src/components/Header.vue
       <App> at src/App.vue
         <Root>

我尝试使用 async/await 发出此请求,我尝试了方法mounted(), created(), beforeMount(), beforeCreate(),但仍然是一样的。我是 Vue.js 的新手,我被困在这里,不知道该怎么办。

编辑整个文件以查看应用程序结构: main.js

import router from './router'
import Vue from 'vue'
import App from './App.vue'
import { BootstrapVue, IconsPlugin } from 'bootstrap-vue'
import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap-vue/dist/bootstrap-vue.css'
import axios from 'axios'
import Vuex from 'vuex'

// Install BootstrapVue
import 'leaflet/dist/leaflet.css';

Vue.use(BootstrapVue)
// Optionally install the BootstrapVue icon components plugin
Vue.use(IconsPlugin)
Vue.use(axios)
Vue.use(Vuex)
Vue.config.productionTip = false

const store = new Vuex.Store({
  state: {
    user : {}
  },
  mutations : {
    set_user (state,user) {
      state.user = user
    }
  }
})

export default store

/* eslint-disable */
router.beforeEach((to, from, next) => {
  if (from.path.indexOf("modificarCatalogo") == -1 && to.path.indexOf("modificarCatalogo") == -1) {
    localStorage.removeItem("catalogue");
  }
  if (localStorage.getItem("token") != null) {
    axios
      .get(`${process.env.VUE_APP_API_BASE_URL}/user/role`, {
        headers: {
          Authorization: "Token " + localStorage.getItem("token")
        }
      })
      .then(response => {
        store.commit('set_user', response.data);
        console.log("First then")
        console.log(store.state.user)
      }).catch(function (error) {
         // handle error case here
         console.log(error);

      }).then(function () {
         // always executed
         console.log("Second then")
         next();
      });
     }else{
        next();
     }
});
/* eslint-enable */

Vue.use(router)

new Vue({
  router,
  render: h => h(App),
}).$mount('#app')

它现在有 Vuex,因为我尝试了 @ellisdod 的回答,但是

应用程序.vue

<template>
  <div>
    <Header />
    <router-view />
    <Footer />
  </div>
</template>

而且,在Header.vue中,这是我调用 Vuex $store 的地方,但它是相同的。我需要它无处不在,所以我尝试调用 App.vue 中的方法但仍然没有结果,它现在使用 Vuex 的解决方案返回一个空对象,但只是空的,而不是用户数据。

export default {
  name: "Header",
  data() {
    return {
      token: localStorage.getItem("token"),
      isOwner: "",
      estancoId: ""
    };
  },
  mounted() {
    console.log("Header log")
    if (this.$store.state.user.role == "Owner") {
      this.isOwner = true;
      this.estancoId = this.$store.state.user.estanco;
    }
  },

我认为其余的组件无关紧要

标签: javascriptvue.jsvuejs2vue-router

解决方案


如果你使用 Vuex 来存储你的用户数据,你可以用一个空对象预填充用户值,这样它就不会抛出错误。

const store = new Vuex.Store({
  state: {
    user : {}
  },
  mutations : {
    set_user (state,user) {
      state.user = user
    }
  },
  actions : {
    loadUserFromLocal ({commit,state}) {
      if (localStorage.getItem("token") === null) return null
      return axios
        .get(`${process.env.VUE_APP_API_BASE_URL}/user/role`, {
        headers: {
          Authorization: "Token " + localStorage.getItem("token")
        }
      })
      .then(response => {
        commit('set_user', response.data);
        console.log("First then")
        console.log(state.user)
      }).catch(function (error) {
         // handle error case here
         console.log(error);
      })

    }
  }
})

new Vue({
  router,
  store,
  render: h => h(App),
}).$mount('#app')

然后在主 App 组件的挂载钩子中添加:

mounted () {
    this.$store.dispatch('loadUserFromLocal')
  }

现在在您的路由器中,而不是在每条路由之前发出服务器请求,您只需检查商店:

if (this.$store.state.user.role) {
  // handle logged in user
}

推荐阅读