动态 Nuxt 页面选择

Posted

技术标签:

【中文标题】动态 Nuxt 页面选择【英文标题】:Dynamic Nuxt page selection 【发布时间】: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 之下 【参考方案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 中合并,在我的项目中运行良好!

【讨论】:

实际上它并没有那么好用,因为路由是在构建时间而不是动态构建的(当用户要求路由时)......我一直在寻找最好的方法。跨度>

以上是关于动态 Nuxt 页面选择的主要内容,如果未能解决你的问题,请参考以下文章

页面重新加载后 Nuxt 动态路由返回 404

Nuxt 根据 .json 文件数据生成动态页面

重新加载页面后,Nuxt动态路由返回404

通过 slug 获取页面和页面数据。 Strapi 和 Nuxt

在客户端的 nuxt 中动态设置正文背景图像

Nuxt.Js 将父页面重定向到索引