【问题标题】:Dynamic Nuxt page selection动态 Nuxt 页面选择
【发布时间】:2020-07-04 19:00:43
【问题描述】:

基本上,我正在尝试为匹配的路由动态选择一个组件,或者进行内部重写,这样我就可以在不更改 url 的情况下选择不同的路由。

我现在的解决方案: 我有来自我想要匹配的外部资源的 url,我正在使用 _.js 在 Nuxt 中使用通配符页面捕获这些。在此页面上的中间件中,我将确定它应该是页面的实际类型(cmspage、productdetail 等)并将结果放入存储中。然后我会检查是否在 validate 函数中找到数据,以便在需要时返回 404。如果成功,将使用渲染函数渲染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')
          }
        }
      })
    }
  }
}

【问题讨论】:

  • 如何确定应该显示哪个页面?什么决定了pageType?。 URL 是否确定要显示的页面类型?
  • @ajobi,是的,该 url 被发送到 magento 和 drupal 以检查他们是否可以解决它,从而确定它是 cms、product 还是 productlistpage。
  • 好的,他们是如何确定的?他们可能会解析 url 寻找蛞蝓等吗?
  • 我相信他们有一个 db 表,他们可以在其中查找完整的 slug,因此我无法匹配特定 url 结构上的页面类型。
  • 你确定吗?因为那将是解决它的明显且正确的方法。我看不出为什么一个产品应该在 product/product-name 之下,而另一个产品应该在一个完全不同的 slug 之下

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


【解决方案1】:

我不确定我的问题是否正确,但我认为:

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

所以,如果这是您想要的,请按照以下说明操作:


  • 内部路线你需要这样的东西:

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 prop 定义的。

我发了CodeSandbox example

【讨论】:

  • 这看起来很像我现在没有 Nuxt 的解决方案,问题是 Nuxt 具有在页面上执行的特殊功能,而不是在组件(中间件、asyncData 等)上执行。这实际上是我想保留的功能,最好让动态页面的行为与 pages 目录中的任何普通页面完全相同。
【解决方案2】:

我不确定我的问题是否正确,但我认为:

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

我有这个解决方案。

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)
      },
    }
  ]
});

【讨论】:

    【解决方案3】:

    我遇到了同样的问题,我在 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 中合并,在我的项目中运行良好!

    【讨论】:

    • 实际上它并没有那么好用,因为路由是在构建时间而不是动态构建的(当用户要求路由时)......我一直在寻找最好的方法。跨度>
    猜你喜欢
    • 1970-01-01
    • 2021-01-17
    • 2020-04-11
    • 1970-01-01
    • 2020-12-23
    • 2014-08-16
    • 2019-11-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多