问题
I'm trying to load routes in a Vue application from my API. I tried pushing data to routes variable and using addRoutes method. But no luck. I think there could be an issue with async. But why the addRoutes() not working?
Here's my code:
import Vue from 'vue';
import VueRouter from 'vue-router';
import axios from 'axios';
/**
* Routes
*/
import item_index from '../../app/Tenant/Item/Views/Index.vue';
import contact_index from '../../app/Tenant/Contact/Views/Index.vue';
import eav_index from '../../app/Tenant/Eav/Views/create.vue';
import eav_create from '../../app/Tenant/Eav/Views/create.vue';
var routes = [
{ path: '/items', component: item_index, name: 'item_index' },
{ path: '/contact', component: eav_index , name: 'contact_index' , props: { entity_type_id: 1 }},
];
Vue.use(VueRouter);
const router = new VueRouter({
mode: 'history',
linkActiveClass: 'active',
routes
});
axios
.get('http://c1.fmt.dev/api/eav/entity_types')
.then(response => {
for (var i = 0; i < response.data.length; i++) {
var type = response.data[i];
var route = {
path: '/' + type.name,
component: eav_index,
name: type.name + '_index',
props: {
entity_type_id: type.id
},
};
router.addRoutes([route]);
alert(router.options.routes);
// alert(JSON.stringify(routes));
}
})
.catch(error => {
console.log(error)
});
new Vue({
el: '.v-app',
data(){
return {
page_header: '',
page_header_small: '',
}
},
router, axios
});
回答1:
Try this improved code. Without postponing Vue instance creation, so without unnecessary delaying page interactivity:
import Vue from 'vue'
import VueRouter from 'vue-router'
import axios from 'axios'
import item_index from '../../app/Tenant/Item/Views/Index.vue'
import contact_index from '../../app/Tenant/Contact/Views/Index.vue'
import eav_index from '../../app/Tenant/Eav/Views/create.vue'
import eav_create from '../../app/Tenant/Eav/Views/create.vue'
Vue.use(VueRouter)
const router = new VueRouter({
mode: 'history',
linkActiveClass: 'active',
routes: [{
path: '/items',
component: item_index,
name: 'item_index'
}, {
path: '/contact',
component: eav_index ,
name: 'contact_index' ,
props: {entity_type_id: 1}
}]
})
new Vue({
el: '.v-app',
router,
data () {
return {
page_header: '',
page_header_small: '',
}
},
methods: {
getDynamicRoutes (url) {
axios
.get(url)
.then(this.processData)
.catch(err => console.log(err))
},
processData: ({data}) => {
data.forEach(this.createAndAppendRoute)
},
createAndAppendRoute: route => {
let newRoute = {
path: `/${route.name}`,
component: eav_index,
name: `${route.name}_index`,
props: {entity_type_id: route.id}
}
this.$router.addRoutes([newRoute])
}
},
created () {
this.getDynamicRoutes('http://c1.fmt.dev/api/eav/entity_types')
}
})
For better code structure and readability, move router definition to separate file:
In your main file, leave just this code:
// main.js
import Vue from 'vue'
import router from '@/router'
import axios from 'axios'
new Vue({
el: '.v-app',
router,
data () {
return {
page_header: '',
page_header_small: '',
}
},
methods: {
getDynamicRoutes (url) {
axios
.get(url)
.then(this.processData)
.catch(err => console.log(err))
},
processData: ({data}) => {
data.forEach(this.createAndAppendRoute)
},
createAndAppendRoute: route => {
let newRoute = {
path: `/${route.name}`,
component: eav_index,
name: `${route.name}_index`,
props: {entity_type_id: route.id}
}
this.$router.addRoutes([newRoute])
}
},
created () {
this.getDynamicRoutes('http://c1.fmt.dev/api/eav/entity_types')
}
})
And in same folder as main file lies, create subfolder 'router' with 'index.js' within:
// router/index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import item_index from '../../../app/Tenant/Item/Views/Index.vue'
import contact_index from '../../../app/Tenant/Contact/Views/Index.vue'
import eav_index from '../../../app/Tenant/Eav/Views/create.vue'
import eav_create from '../../../app/Tenant/Eav/Views/create.vue'
Vue.use(VueRouter)
export default new VueRouter({
mode: 'history',
linkActiveClass: 'active',
routes: [{
path: '/items',
component: item_index,
name: 'item_index'
}, {
path: '/contact',
component: eav_index ,
name: 'contact_index' ,
props: {entity_type_id: 1}
}]
})
回答2:
The vue instance is already initiated when you try to add the routes (same problem as in this question: How to use addroutes method in Vue-router? ). You could postpone the vue initalization after the routes are loaded:
//imports and stuff...
axios
.get('http://c1.fmt.dev/api/eav/entity_types')
.then(response => {
for (var i = 0; i < response.data.length; i++) {
var type = response.data[i];
var route = {
path: '/' + type.name,
component: eav_index,
name: type.name + '_index',
props: {
entity_type_id: type.id
},
};
// extend routes array prior to router init
routes.push(route);
}
// init router when all routes are known
const router = new VueRouter({
mode: 'history',
linkActiveClass: 'active',
routes
});
// init vuw instance when router is ready
new Vue({
el: '.v-app',
data(){
return {
page_header: '',
page_header_small: '',
}
},
router, axios
});
})
.catch(error => {
console.log(error)
});
来源:https://stackoverflow.com/questions/53132533/load-routes-from-api-in-vue