Vue .prototype не определен при первой загрузке страницы - PullRequest
0 голосов
/ 27 марта 2020

Итак, я пытаюсь сделать запрос с топором ios в моем main.js файле.

Я использую, как показано, vue -рутер, чтобы сделать этот запрос перед каждым Компонент загружен. Однако я не могу заставить это работать, когда моя веб-страница загружается впервые. Я имею в виду, что запрос ax ios выполняется после загрузки компонента. Затем произойдет сбой:

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>

Я попытался сделать этот запрос с асинхронным / ожиданием, я пытался методы 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>

И, в Заголовок. 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;
    }
  },

Остальные компоненты не имеют значения, я думаю

Ответы [ 2 ]

0 голосов
/ 27 марта 2020

Если вы используете 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')

Затем в подключенном хуке вашего основного компонента приложения добавьте:

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

Теперь в вашем маршрутизаторе вместо того, чтобы делать запросы к серверу перед каждым маршрутом, вы просто проверяете хранилище:

if (this.$store.state.user.role) {
  // handle logged in user
}
0 голосов
/ 27 марта 2020

Привет,

Полный ответ, основанный на редактировании вопроса, комментариях и ответах:

Проблема

Vue Метод beforeEach -router будет выполняться только в компонентах, которые определены в маршрутах. В вашем случае

  1. beforeEach не будет вызываться в компоненте Header , поскольку он не является частью маршрутизации. Это отдельный компонент. Поэтому вы не можете получить к нему доступ $user.

store. js

    import axios from 'axios'
    import Vuex from '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);
          })

        }
      }
    })
    export default store

@ ellisdod - спасибо.

Теперь вы можете использовать пользовательскую переменную из хранилища в вашем компоненте, и она будет обновлена ​​после завершения выборки данных или покажет начальные значения до этого времени

Поэтому нет необходимости извлекать данные в router.beforeEach router. js

    // --> all imports
    import store from './store' // --> added
    //  --> all routes to be defined here... 

    router.beforeEach((to, from, next) => {
     // --> other logic for filtering routes
     // --> you can use 'store' variable here to get the user data and add 
    filtering 
    if (from.path.indexOf("modificarCatalogo") == -1 && 
    to.path.indexOf("modificarCatalogo") == -1) {
    localStorage.removeItem("catalogue");
     }
     next();

    });

Как вы знаете в vue -router, если вызывается next, то говорят, что навигация подтверждена, и компонент будет визуализирован. Также для получения дополнительной информации об использовании переменной store внутри router.beforeEach метода см. этот вопрос

основной. js

    import router from './router'

    import store from './store' // --> added

    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


    Vue.use(router)

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

Приложение. vue

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

@ ellisdod - спасибо.

Заголовок. vue

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

...