Answer the question
In order to leave comments, you need to log in
How to solve the problem with initialization of the initial state of the Vue.js application?
Good afternoon! Help, knowledgeable people, to understand the following problem:
I am developing a pet on the Vue.js front and Symfony 4 back. Before initializing the application, it is necessary to make a request to the server in order to get routes for api and some other "primary" data - whether the user is authorized, if yes - information about him. The problem is that the request is asynchronous and the data arrives in the application a little later than the application is rendered. I make a request to get api routes in the hook (I tried it in created, beforeCreated, mounted) App.vue, I tried to make it in the main js file, in which the Vue instance is actually created, and create new Vue in the successful callback of this primary request, but there got out a problem with writing the primary data received via api to $store.
Detailed description with files:
The file where modules, router, stores are connected, a Vue instance is created.
import Vue from 'vue';
import axios from 'axios';
import vueAxios from 'vue-axios';
import Vuex from 'vuex';
import VueRouter from 'vue-router';
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import App from './vue/App';
import LoginForm from './vue/element/LoginForm';
import ItemsList from './vue/element/ItemsList';
require('../css/app.styl');
Vue.component('App', App);
Vue.use(VueRouter);
Vue.use(vueAxios, axios);
Vue.use(Vuex);
Vue.use(ElementUI);
Vue.use(LoginForm);
const router = new VueRouter({
mode: 'history',
routes: [
{path: '/', component: LoginForm, name: 'LoginForm'},
{path: '/list/', component: ItemsList, name: 'ItemsList'},
],
});
const store = new Vuex.Store({
state: {
isAuth: false,
user: {},
itemsList: {},
filterOptions: {},
path: router.currentRoute.path,
api: {},
pagination: {},
},
mutations: {
set(state, {type, value}) {
state[type] = value;
},
go(state, {path}) {
router.push(path);
state.path = path;
},
multiSet(state, {value}) {
for (let key in value) {
state[key] = value[key];
}
}
},
getters: {
getPath: state => {
state.path = router.currentRoute.path;
return state.path;
},
},
});
const vm = new Vue({
el: '#app',
router,
store
});
<template>
<div class="app">
<header-navigator :defaultIndexProp="defaultIndexProp"></header-navigator>
<transition name="el-fade-in" mode="out-in">
<router-view @goToList="toList" v-if="api"></router-view>
</transition>
</div>
</template>
<script>
import HeaderNavigator from './element/HeaderNavigator';
import LoginForm from "./element/LoginForm";
export default {
name: 'app',
components: {
LoginForm,
HeaderNavigator
},
computed: {
api() {
return this.$store.state.api;
}
},
data() {
return {
defaultIndex: window.location.path,
defaultIndexProp: window.location.path,
}
},
methods: {
toList() {
this.defaultIndexProp = '/list/';
}
},
mounted() {
this.axios.get('/api/init/').then(r => {
const {data} = r;
this.$store.commit('multiSet', {value: data});
});
}
}
</script>
<style>
</style>
<template>
<el-card></el-card>
</template>
<script>
export default {
name: 'ItemsList',
data() {
return {
}
},
computed: {
api() {
return this.$store.state.api;
}
},
created() {
this.axios({
url: this.api.items.path,
method: this.api.items.method
}).then(r => {
const {data} = r;
this.$store.commit('multiSet', {value: data});
}).catch(e => {
});
}
}
</script>
<style lang="stylus">
</style>
Answer the question
In order to leave comments, you need to log in
You can switch components: https://codepen.io/anon/pen/oMWNrm
or mount only after receiving all the data: https://codepen.io/anon/pen/oMWgLR
If I were you, I would create a separate download page, describe all the initial data loading when logging in on this page. Displayed, in the meantime, some kind of spinner, when all the data was loaded into the store, I would simply do router.push. I actually do this on projects where I need to use a lot of data that I get from the server. In general, there is still such a problem that you are trying to reactively bind data that is stored in an object that does not yet exist, in which case we encounter the problem of reactive binding in Vue and here either use a crutch in the form of Vue.set or beat the object into variables if it the structure is known to be known, or else determine its default value. I hope I described all the pitfalls that you will encounter in this direction
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question