全动态vue-router

War*_*sse 7 vue.js vue-router nuxt.js

我们正在构建一个基于 Vue 和 Nuxt 的庞大网站,其中包含超过 25 种不同的页面类型,这些页面类型无法与 Vue Router 开箱即用的标准 /:id 或 /overview/:slug 逻辑匹配。

由于 slug-matching 不是一种选择,我们正在考虑以下解决方案:

  1. 用户访问页面“/this-is-a-topic-page”
  2. 服务器调用返回 pageType 的 API topicPage
  3. topicPage 与nuxt页面有关 WpTopicPage
  4. 我们WpTopicPage在 Vue Router 的通配符实例中设置为我们的组件

代码如下:

export function createRouter() {
  return new Router({
    mode: 'history',
    routes: [
      // 1. User visits page "/this-is-a-topic-page"
      {
        name: 'wildcard',
        path: '*',
        component: *, // this should be dynamic
        beforeEnter: (to, from, next) => {
          // 2. Server calls API that returns the pageType `topicPage`
          this.$axios.get(`/call-to-the-api?slug=${to.params.slug}`)
            .then((res) => {
              // 3. `topicPage` relates to the nuxt page `WpTopicPage`
              if(res.data.pageType === 'topicPage') {
                // 4. Set `WpTopicPage` as our Page component
                return WpTopicPage;
              }
            })
        },
      },
    ],
  });
}
Run Code Online (Sandbox Code Playgroud)

以上显然行不通。有没有办法component在 beforeEnter 函数中动态设置路由内的?

And*_*mig 3

这是可以做到的。我创建了一个codepen供您测试:

这里是:

Vue.use(VueRouter);

let A = {
  mounted() {
    console.log('Mouted component A');
  },
};
let B = {
  mounted() {
    console.log('Mouted component B');
  },
};
let C = {
  mounted() {
    console.log('Mouted component C');
  },
};

const router = new VueRouter({
  mode: "hash",
  routes: [
    {
      path: '*',
      beforeEnter(to, from, next) {
        let components = {
          default: [A, B, C][Math.floor(Math.random() * 100) % 3],
        };
        to.matched[0].components = components;
        
        next();
      }
    },
  ]
});

app = new Vue({
  router,
  el: '#app',
  components: { A, B, C }
});
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue-router/3.0.2/vue-router.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <router-link :to="'/' + Math.random()">anything</router-link>
  <router-view></router-view>
</div>
Run Code Online (Sandbox Code Playgroud)

这是输出:

在此输入图像描述

正如您在控制台日志中看到的那样 - 每次发生变化时,我们都会加载和安装随机组件。