从子项中排除嵌套组件(Nuxt 路由)

问题描述 投票:0回答:3

是否可以从父组件的子组件中排除 pages 目录中的某些嵌套组件?我需要一些嵌套组件(

nested-a
nested-b
)在父组件(
_id.vue
)内部渲染,一些嵌套组件(独立嵌套)用作独立页面,不在
_id.vue
内部渲染,仅使用父组件在路线中。

所以我的目标是实现这些路线:

  • /account/{id}
    - 主页
  • /account/{id}/standalone-nested
    - 独立页面,不在父级内部呈现
  • /account/{id}/nested-a
    /account/{id}/nested-b
    - 在 parent 内渲染的嵌套组件

这是我的目录树:

pages
├── account
│   ├── _id
│   │   ├── nested-a.vue
│   │   ├── nested-b.vue
│   │   └── standalone.vue
│   ├── _id.vue
│   └── index.vue
└── index.vue

生成以下路由器:

{
    path: "/en/account/:id",
    component: _45553d28,
    name: "account-id___en",
    children: [{
      path: "nested-a",
      component: _7b67c342,
      name: "account-id-nested-a___en"
    }, {
      path: "nested-b",
      component: _7b75dac3,
      name: "account-id-nested-b___en"
    }, {
      path: "standalone",
      component: _6884b488,
      name: "account-id-standalone___en"
    }]
  }

在我的父组件中

_id.vue
我正在使用
<NuxtChild  />
来确保在这个组件内渲染嵌套组件,但我不知道如何告诉nuxt哪些嵌套组件只在这个标签内渲染。

这是我的 MWE:https://github.com/DenisStephanov92/nuxt-routing-sample

感谢您的任何建议。

javascript vuejs2 nuxt.js vue-router
3个回答
2
投票

我遇到了和你一样的问题,虽然可能为时已晚。但如果有人遇到类似问题,我会留下这个答案。


从你的情况来看,你想让

standalone.vue
与父母
_id.vue
分开。但是你仍然想使用与另一个孩子相同的子路线。

你实际上可以在

extendRoutes
中使用
nuxt.config.js
来修改生成的路线。
P.S:虽然没有必要采用干净的方法。


nuxt.config.js
中,您可以将
extendRoutes
添加到
router
,并使用unshift和filter对其进行修改。就像这样

router: {
  extendRoutes(routes, resolve) {
    routes.find(el => el.name === 'account-id___en')
      .children
      .filter(el => el.name !== 'account-id-standalone___en');
    routes.unshift({
      path: "/en/account/:id/standalone",
      component: resolve(__dirname, 'pages/account/_id/standalone.vue'),
      name: "account-id-standalone___en"
    });
  },
},

结果:

[
  {
    path: "/en/account/:id/standalone",
    component: _6884b488,
    name: "account-id-standalone___en"
  },
  {
    path: "/en/account/:id",
    component: _45553d28,
    name: "account-id___en",
    children: [
      {
        path: "nested-a",
        component: _7b67c342,
        name: "account-id-nested-a___en"
      },
      {
        path: "nested-b",
        component: _7b75dac3,
        name: "account-id-nested-b___en"
      },
    ],
  },
]

参考:https://nuxtjs.org/docs/configuration-glossary/configuration-router/#extendroutes


0
投票

不确定我是否完全明白你想要实现的目标,但我做了 2 个按钮:

  • 主页按钮:有条件地呈现
    standalone
    而不是选项卡,但仍将视图保持在其父级(路径以
    standalone-nested
    结尾)
  • 真正的外部按钮:完全不相关的页面,但仍然可以在您希望的路径上访问,现在它在
    external-standalone-nested
    上,但您可以简单地更改它。为此,转到
    external-standalone.vue
    并在
    <router></router>
    部分进行更改。

所有这一切都归功于

@nuxtjs/router-extras
包。
我希望它能以某种方式帮助你。当然,您可以修改它,使其具有独立显示与非独立显示的特定布局。
你当然也可以将
external-standalone.vue
文件移动到
account
目录中,如果你想在同一级别拥有
_id.vue

我在 Codesandbox 上托管了解决方案,我的提交 - 从您的分叉示例开始 - 可以在 Github 上找到。

编辑:我再次承诺。删除了无用的注释并添加了一个动态组件示例,因为它是一个有趣的模式,可以通过其他方式帮助您bypass

nuxt-child

与我们的用例不完全相关,但值得一看 IMO。


0
投票

您可以通过手动扩展路由配置来完成此操作,但我编写了一个函数来为您自动执行此操作。使用它的方法是在您想要成为子页面的页面前加上

&
(这些页面将位于与其父页面同名的文件夹中)。这些文件夹中的任何其他页面将从子项中删除,并且将在没有父项的情况下呈现。该函数以递归方式工作。如果需要,您可以更改前置符号。

一些例子:

// parent1 > &child1 > parent2 > &child2 will render child1 inside parent1, not parent2 NOT in child1, child2 in parent2:
/parent1/child1/parent2
  /child2
/parent1
  /child1

// parent1 > &child1 > &parent2 > &child2 will render child1 inside parent1, parent2 in child1, and child2 in parent2:
/parent1
  /child1
    /parent2
      /child2
const CHILD_CHAR = "&";
const URIENCODED_CHILD_CHAR = encodeURIComponent(CHILD_CHAR);

const removePathAmpersands = (path: string) => {
    return path.replace(new RegExp(`(^|\/)${URIENCODED_CHILD_CHAR}`, 'g'),  "$1");
}

const removeNameAmpersands = (name: string) => {
    return name.replace(new RegExp(`(^|-)${CHILD_CHAR}`, 'g'), "$1");
}

/**
 * When using nuxt-child, all sub-pages are by default rendered in the same parent.
 * This parser will recursively check if a child path starts with an `&`. If it does not, the route will not be a child.
 */
const nuxtChildDepthParser = (routes: any[] = [], siblings?: any[], fullPath = "") => {
    const newSiblings = [] as typeof routes;

    let i = routes.length;
    while (i--) {
        const route = routes[i];
        nuxtChildDepthParser(route.children, newSiblings, fullPath + removePathAmpersands(route.path) + "/");
        if (!route.children?.length) delete route.children;

        if (fullPath) {
            route.name = removeNameAmpersands(route.name);
            if (route.path.startsWith(URIENCODED_CHILD_CHAR)) {
                route.path = removePathAmpersands(route.path);
            } else {
                // we should move this page up
                route.path = fullPath + removePathAmpersands(route.path);
                newSiblings.push(route);
                routes.splice(i, 1);
            }
        }
    }

    const parentSiblings = siblings ?? routes;
    parentSiblings.push(...newSiblings);
    parentSiblings.sort((a, b) => !a.children && b.children ? -1 : 1);
};

然后像这样扩展你的路由器:

router: {
    extendRoutes(routes, _resolve) {
        nuxtChildDepthParser(routes)
    }
},

我不确定

sortRoutes()
中的
import {sortRoutes} from "@nuxt/utils"
是否真的需要,但以防万一。

© www.soinside.com 2019 - 2024. All rights reserved.