VueJS динамические маршруты и компоненты - PullRequest
0 голосов
/ 27 сентября 2018

Использование cue-cli 3. Возможно ли это сделать (router.js):

axios.get( `${process.env.VUE_APP_API_DOMAIN}/wp-json/api/v1/routes`).then( r => r.data ).then(routes => {
    routes.pages.forEach( (e) => {
        router.addRoutes([
            {
                path: `/${e.slug}`,
                component: e.template,
            },
        ]);
    });
});

e.template - это строка 'Default' и, конечно, VueJS говорит: route config "component" for path: /privacy-policy cannot be a string id. Use an actual component instead. Пробовал сVue.component(e.template) не повезло.

Здесь я хочу создать динамические маршруты на основе ответа XHR.

Вот весь код router.js:

import Vue from 'vue'
import Router from 'vue-router'
import Home from './views/Home.vue'
import Default from './views/Default.vue'
import Test from './views/Test.vue'
import axios from "axios";

Vue.use(Router);

const router = new Router({
  mode: 'history',
  base: process.env.BASE_URL,
  routes: [
    {
      path: '/',
      name: 'home',
      component: Home
    },
  ]
});

axios.get( `${process.env.VUE_APP_API_DOMAIN}/wp-json/api/v1/routes`).then( r => r.data ).then(routes => {
    routes.pages.forEach( (e) => {
        router.addRoutes([
            {
                path: `/${e.slug}`,
                component: e.template,
            },
        ]);
    });
});

export default router;

Ответы [ 2 ]

0 голосов
/ 27 сентября 2018

В настоящее время я получил следующее решение:

function getComponent(name) {

    let component = null;

    switch(name)
    {
        case 'Default':
            component = Default;
            break;

        case 'Test':
            component = Test;
            break;
    }

    return component;

}

axios.get( `${process.env.VUE_APP_API_DOMAIN}/wp-json/api/v1/routes`).then( r => r.data ).then(routes => {
    routes.pages.forEach( (e) => {
        router.addRoutes([
            {
                path: `/${e.slug}`,
                component: getComponent(e.template),
            },
        ]);
    });
});

Еще одно более чистое решение:

const components = { Default, Test }

axios.get( `${process.env.VUE_APP_API_DOMAIN}/wp-json/api/v1/routes`).then( r => r.data ).then(routes => {
    routes.pages.forEach( (e) => {
        router.addRoutes([
            {
                path: `/${e.slug}`,
                component: components[e.template],
            },
        ]);
    });
});
0 голосов
/ 27 сентября 2018

Если e.template хранит строку шаблона,

Вы должны обернуть ее как один объект параметров, такой как {template: e.template, props: {}, data: function () {} }, затем вызвать Vue.extend для создания компонента.

или вы можетеигнорируйте Vue.extend, потому что Vue вызовет Vue.extend для автоматического создания компонента.

Проверьте использование в Vue Guide: Vue.component

Редактировать в качестве состояния OP e.tempate - это имя одного компонента:

, если e.template - это имя компонента, используется Vue.component(e.template).

Vue.config.productionTip = false
const router = new VueRouter({
  routes: [
  ]
})

Vue.component('test', {
  template: '<div>I am Predefined component -> {{index}}</div>',
  props: ['index']
})

let routerIndex = 1
setInterval(()=> {
  let newComponent = routerIndex%2 ? {template: '<div>I am User -> {{index}}</div>', props: ['index']} : Vue.component('test')
  
  router.addRoutes([{
    path: '/Test' + routerIndex,
    name: 'Test' + routerIndex,
    component: newComponent,
    props: { index: routerIndex }
  }])
  console.log('add route = ', '/Test' + routerIndex, ' by ', routerIndex%2 ? 'options object' : 'Vue.component')
  routerIndex++
}, 2000)

Vue.use(VueRouter)
app = new Vue({
  el: "#app",
  router,
  data: {
    routeIndex: 0
  },
  watch: {
    routeIndex: function (newVal) {
      this.$router.push({'name': 'Test'+newVal})
    }
  }
})
div.as-console-wrapper {
  height: 100px;
}
<script src="https://unpkg.com/vue@2.5.16/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<div id="app">
    <p>Current Route Index: {{routeIndex}}</p>
    Test Route: <input v-model="routeIndex" type="number">
    <router-view></router-view>
</div>
...