动态Nuxt页面选择

时间:2020-03-24 09:41:29

标签: javascript vue.js vue-router nuxt.js

基本上,我正在尝试为匹配的路由动态选择一个组件或进行内部重写,以便我可以选择其他路由而不更改url。

我现在的解决方案: 我的网址来自我要匹配的外部资源,我正在使用_.js在Nuxt中使用通配符页面捕获这些网址。在此页面上的中间件中,我将确定页面的实际类型(cmspage,productdetail等),并将结果放入商店中。然后,我将检查是否在validate函数中找到了数据,以便在需要时可以返回404。如果成功,则可以使用render函数来渲染components/pages/cms.vue或任何类型的页面。

所以这应该工作(仍然需要大部分实现),但存在一个问题,就是我无法使用许多可用于以下方面的Nuxt功能(中间件,asyncData,获取,验证等等)?页面正是我要实现的目标。

此nuxt配置扩展名不起作用,但将是完美的:

{
  router: {
    extendRoutes(routes, resolve) {
      routes.push({
        path: '*',
        component: async () => {
          const pageType = 'pdp' // await getPageType()
          switch (pageType) {
            case 'cms':
              return resolve(__dirname, 'pages/cmsPage.vue')
            case 'pdp':
              return resolve(__dirname, 'pages/productDetailPage.vue')
            case 'plp':
              return resolve(__dirname, 'pages/productListPage.vue')
          }
        }
      })
    }
  }
}

3 个答案:

答案 0 :(得分:3)

我不确定是否能正确回答问题,但我认为:

  • 您想要一个路径(路线)来显示不同的(动态)视图
  • 在路由加载之前,您要获取页面类型(可能是从后端获取)
  • 如果这些组件与路线不匹配,您不希望将这些组件加载到您的应用程序中

因此,如果您要这样做,请按照以下步骤操作:


  • 内部路线中,您需要这样的东西:

let pageType = null;

export default new VueRouter({
  mode: "history",
  routes: [
    //... other routes
    {
      path: "/dynamic-page",
      component: () => import("./components/DynamicPage"),
      props: router => ({ pageType }),
      beforeEnter(to, from, next) {
        // getPageType() is supposed as a async method getting the page type
        getPageType().then(type => {
          pageType = type;
          next();
        });
      }
    }
  ]
});

因此,使用上面的代码,我们获取了pageType并将其作为prop传递给组件。

  • 接下来,创建应加载不同组件的动态组件
<template>
  <div class="dynamic-page">
    <component :is="pageType"/>
  </div>
</template>

<script>
export default {
  props: {
    pageType: String
  },

  components: {
    ProductList: () => import("../dynamic-pages/ProductListPage"),
    Cms: () => import("../dynamic-pages/CmsPage"),
    ProductDetail: () => import("../dynamic-pages/ProductDetailPage")
  }
};
</script>

因此使用延迟加载的组件将仅加载1个组件。这是由pageType道具定义的。

我做了一个CodeSandbox example

答案 1 :(得分:0)

我不确定是否能正确回答问题,但我认为:

您要根据某些条件动态加载页面。

我有这个解决方案。

import Vue from "vue";
import VueRouter from "vue-router";
import HomePage from "./components/HomePage";

Vue.use(VueRouter);

function getRandomPage() {
  const pageTypes = ["ProductList", "Cms", "ProductDetail"];
  let min = 0;
  let max = 2;
  min = Math.ceil(min);
  max = Math.floor(max);
  const random = Math.floor(Math.random() * (max - min + 1)) + min;
  return pageTypes[random];
}

let pageType = null;

function getPageType() {
  return new Promise(res => setTimeout(res(getRandomPage()), 1500));
}

export default new VueRouter({
  mode: "history",
  routes: [
    {
      path: "/",
      component: HomePage
    },

    {
      path: "/dynamic-page",
      component: () => {
        let page = "ProductListPage.vue"
        getPageType().then(type => {
          pageType = type;
          console.log(pageType)
          if (pageType === "ProductList") {
            page = "ProductListPage.vue";
          } else if (pageType === "Cms") {
            page = "CmsPage.vue";
          } else {
            page = "ProductDetailPage.vue";
          }
        })

        return import("./dynamic-pages/" + page)
      },
    }
  ]
});

答案 2 :(得分:0)

我遇到了同样的问题,我在github上找到了这个PR:https://github.com/nuxt/nuxt.js/pull/7754

解决方案如下:

{
  router: {
    async extendRoutes(routes, resolve) {
      const pageType = await getPageType()
      let component
      switch (pageType) {
            case 'cms':
              component = resolve(__dirname, 'pages/cmsPage.vue')
            case 'pdp':
              component = resolve(__dirname, 'pages/productDetailPage.vue')
            case 'plp':
              component = resolve(__dirname, 'pages/productListPage.vue')
      }
      routes.push({
        path: '*',
        component
      })
    }
  }
}

它已在v2.14.0中合并,并且在我的项目中运行良好!