【问题标题】:How do I navigate to a parent route from a child route?如何从子路由导航到父路由?
【发布时间】:2023-04-06 11:43:01
【问题描述】:

我的问题很经典。我有一个应用程序的私有部分,它位于login form 后面。登录成功后,转到管理应用程序的子路由。

我的问题是我不能使用global navigation menu,因为路由器试图在我的AdminComponent 中路由,而不是我的AppCompoment。所以我的导航坏了。

另一个问题是,如果有人想直接访问 URL,我想重定向到父“登录”路由。但我不能让它工作。在我看来,这两个问题是相似的。

知道怎么做吗?

【问题讨论】:

  • 请添加一些代码
  • 正如其他人所指出的,请添加一些代码或基本路由配置,以便您的问题可以吸引更准确的答案。

标签: angular angular-routing angular-router


【解决方案1】:

您想要链接/HTML 还是要以命令方式/在代码中路由?

链接:RouterLink 指令始终将提供的链接视为当前 URL 的增量:

[routerLink]="['/absolute']"
[routerLink]="['../../parent']"
[routerLink]="['../sibling']"
[routerLink]="['./child']"     // or
[routerLink]="['child']" 

// with route param     ../../parent;abc=xyz
[routerLink]="['../../parent', {abc: 'xyz'}]"
// with query param and fragment   ../../parent?p1=value1&p2=v2#frag
[routerLink]="['../../parent']" [queryParams]="{p1: 'value', p2: 'v2'}" fragment="frag"

使用RouterLink,记得导入和使用directives数组:

import { ROUTER_DIRECTIVES } from '@angular/router';
@Component({
    directives: [ROUTER_DIRECTIVES],

命令式navigate() 方法需要一个起点(即relativeTo 参数)。如果没有提供,导航是绝对的:

import { Router, ActivatedRoute } from '@angular/router';
...
constructor(private router: Router, private route: ActivatedRoute) {}
...
this.router.navigate(["/absolute/path"]);
this.router.navigate(["../../parent"], {relativeTo: this.route});
this.router.navigate(["../sibling"],   {relativeTo: this.route});
this.router.navigate(["./child"],      {relativeTo: this.route}); // or
this.router.navigate(["child"],        {relativeTo: this.route});

// with route param     ../../parent;abc=xyz
this.router.navigate(["../../parent", {abc: 'xyz'}], {relativeTo: this.route});
// with query param and fragment   ../../parent?p1=value1&p2=v2#frag
this.router.navigate(["../../parent"], {relativeTo: this.route, 
    queryParams: {p1: 'value', p2: 'v2'}, fragment: 'frag'});

// navigate without updating the URL 
this.router.navigate(["../../parent"], {relativeTo: this.route, skipLocationChange: true});

【讨论】:

  • router.navigate(string) 方法在当前版本的 Angular (2.2) 中似乎不存在。我在docs 中搜索,只找到navigate(commands: any[], extras?: NavigationExtras) : Promise<boolean>。还是我完全错过了什么?
  • @Tomato,你需要在路线周围加上 []。例如 this.router.navigate(["../../parent"], {relativeTo: this.route});
  • 当您在 html 中使用 [routerLink] 而不是 typescript 时,如何传递 relativeTo 数据?
  • 服务也一样?
  • 出于某种原因,在我的情况下,我必须使用../../../ 而不是../ 导航到父级('/users' 来自'/users/1')。
【解决方案2】:

截至 2017 年春季,这似乎对我有用:

goBack(): void {
  this.router.navigate(['../'], { relativeTo: this.route });
}

你的组件ctor接受ActivatedRouteRouter的地方,导入如下:

import { ActivatedRoute, Router } from '@angular/router';

【讨论】:

  • 提及您碰巧使用的 Angular 版本比提及日期更有用。
  • @isherwood 我同意。道歉。如果我没记错的话,我是为 Angular 4.0.x 编写的,它在 4.3.x 中仍然有效。不幸的是,我现在已经离开了 Angular,
  • @ne1410s 非常感谢缺少亲戚:this.route
  • 注意:不会在延迟加载的模块上使用额外的路由器段。例如:parentPath: 'work:queue'(有孩子)并说孩子用参数加载子模块。 fullCurrentPath: '工作/运输/模块/列表'。以上代码无法从fullCurrentPath加载parentPath
【解决方案3】:

你可以像这样导航到你的父根目录

this.router.navigate(['.'], { relativeTo: this.activeRoute.parent });

您需要在构造函数中注入当前活动的路由

constructor(
    private router: Router,
    private activeRoute: ActivatedRoute) {

  }

【讨论】:

  • 添加一些解释会使这个答案更有用。
  • 很多人建议通过 this.router.navigate(["../sibling"], {relativeTo: this.route});但是,这不再起作用了。我发现这个答案可能有效。而不是使用 '../' 导航到父级。将 relativeTo 从 this.route 更改为 this.route.parent 是正确的方法
  • @ChrisLamothe:哦,是的,我犯了一个错误。它在一般情况下有效。但是,它不适用于辅助路线。这意味着 this.router.navigate(['../sibling']) 正在工作,但不是 this.router.navigate([{outlets: {'secondary': ['../sibling']}}])。在辅助路由中,我必须使用 this.router.navigate([{outlets: {'secondary': ['sibling']}}], {relativeTo:this.activatedRoute.parent})。
  • 此外,当您在 /users/create 和 /users/edit/123 两个路径中使用相同组件时,此答案 this.router.navigate(['.'], {relativeTo: this.activeRoute.parent}); 中的导航方法将正常工作。在这两种情况下,它都会导航到父/用户。 this.router.navigate([".."], {relativeTo: this.activeRoute}) 的常规导航仅适用于 users/create,但不适用于 users/edit/123,因为它将导航到不存在的 /users/edit/ 路由。
  • +1 作为替代方案,但就我个人而言,我是一个字节追逐者,并且会在参数 [".."] 中添加一个额外的点,以消除对父级的引用,{ relativeTo: this.route }.
【解决方案4】:
constructor(private router: Router) {}

navigateOnParent() {
  this.router.navigate(['../some-path-on-parent']);
}

路由器支持

  • 绝对路径/xxx - 在根组件的路由器上启动
  • 相对路径xxx - 在当前组件的路由器上启动
  • 相对路径../xxx - 在当前组件的父路由器上启动

【讨论】:

  • 尽管此代码可能会回答问题,但提供有关 why 和/或 如何 回答问题的额外上下文将显着改善其长期价值。请edit你的答案添加一些解释。
  • @TobySpeight 够公平的。我以为../ 是众所周知的,但最终它仍然模棱两可。感谢您的提示。
  • 感谢您的回答,我已经在这个网站上工作了很长一段时间,所以 Angular 显然已经更新了。我已经在我当前的版本中尝试过这个解决方案,但它不起作用。让我更新,我会在之后发表评论。
  • 我没有让您的代码按预期工作。但是,通过显式添加 , { relativeTo: this.route } 作为调用 navigate 的第二个参数,它可以工作。如果不是因为您的答案通常具有极高的准确性,我会将其归结为一个愚蠢的错字。自提供答案以来,路由器的行为是否发生了变化(3.6 年前,在 Angular 年代,这就像半个永恒)?
  • 这是一个旧答案,此时路由器发生了很大变化。考虑到有几个答案有更多的赞成票,我认为我的答案已经过时了。我不再做那么多 Web UI 的事情,也没有想到所有的细节。
【解决方案5】:

另一种方式可能是这样的

this._router.navigateByUrl(this._router.url.substr(0, this._router.url.lastIndexOf('/'))); // go to parent URL

这里是构造函数

constructor(
    private _activatedRoute: ActivatedRoute,
    private _router: Router
  ) { }

【讨论】:

    【解决方案6】:

    事不宜迟:

    this.router.navigate(['..'], {relativeTo: this.activeRoute, skipLocationChange: true});
    

    参数 '..' 使导航向上一级,即父级:)

    【讨论】:

    • 您可能想提及 skipLocationChange 的目的/需要。
    • 在前面的注释之外,添加对“this.activeRoute”有什么关系的引用
    【解决方案7】:

    要导航到父组件而不考虑当前路由或父路由中的参数数量:Angular 6 update 1/21/19

       let routerLink = this._aRoute.parent.snapshot.pathFromRoot
            .map((s) => s.url)
            .reduce((a, e) => {
                //Do NOT add last path!
                if (a.length + e.length !== this._aRoute.parent.snapshot.pathFromRoot.length) {
                    return a.concat(e);
                }
                return a;
            })
            .map((s) => s.path);
        this._router.navigate(routerLink);
    

    这有一个额外的好处,就是你可以与单例路由器一起使用的绝对路由。

    (肯定是 Angular 4+,也可能是 Angular 2。)

    【讨论】:

    • 奇怪的是,这总是返回一个空数组,并达到与this._router.navigate([]) 相同的结果,而this._router.navigate([[]]) 采用父路由,当且仅当父路由本身不是根路由。
    • 更新了代码以反映 Angular 6 的更改和正确的父查找,父子节点在路由中包含子节点。
    • 您确定这不是您的用例所特有的吗?似乎没有附加最后一条路径会将 ['orders', '123', 'items', 1] 变成只是 ['orders'],这似乎根本不对。无论如何,我们只是从 Angular 5 升级到 7 并没有触及这个代码。
    • 它们是我页面上 div 的数量。点击每个 div 时,我都会传递查询参数并加载组件。现在使用浏览器返回按钮我想返回怎么做?
    【解决方案8】:

    我的路线有这样的模式:

    • user/edit/1 -> 编辑
    • user/create/0 -> 创建
    • 用户/ -> 列表

    例如,当我在编辑页面时,我需要返回列表页面,我将在路线上返回 2 个级别。

    考虑到这一点,我使用“级别”参数创建了我的方法。

    goBack(level: number = 1) {
        let commands = '../';
        this.router.navigate([commands.repeat(level)], { relativeTo: this.route });
    }
    

    所以,要从编辑转到列表,我会这样调用方法:

    this.goBack(2);
    

    【讨论】:

      【解决方案9】:

      如果您使用的是 uiSref 指令,那么您可以这样做

      uiSref="^"
      

      【讨论】:

        【解决方案10】:

        我的解决办法是:

        const urlSplit = this._router.url.split('/');
        this._router.navigate([urlSplit.splice(0, urlSplit.length - 1).join('/')], { relativeTo: this._route.parent });
        

        还有Router注入:

        private readonly _router: Router
        

        【讨论】:

          【解决方案11】:

          这些都不适合我...这是我的带有后退功能的代码:

          import { Router } from '@angular/router';
          ...
          constructor(private router: Router) {}
          ...
          back() {
             this.router.navigate([this.router.url.substring(0, this.router.url.lastIndexOf('/'))]);
          }
          

          this.router.url.substring(0, this.router.url.lastIndexOf('/') --> 获取当前url“/”后的最后一部分 --> 获取当前路由。

          【讨论】:

          • 请更新您的答案,并说明为什么会这样。请参阅How to Answer
          【解决方案12】:

          这可能会有所帮助:https://angular.io/api/router/ExtraOptions#relativeLinkResolution

          ExtraOptions界面
          路由器模块的一组配置选项,在 forRoot() 方法中提供。

          interface ExtraOptions {
           // Others omitted
           relativeLinkResolution?: 'legacy' | 'corrected'
          }
          

          relativeLinkResolution?: 'legacy' | 'corrected'

          启用错误修复,以纠正具有空路径的组件中的相对链接分辨率。
          >
          更正了 v11 中的默认设置。

          过去几天我一直在为路由而苦苦挣扎,结果发现以前在相对路由中存在错误。这解决了它。

          【讨论】:

            【解决方案13】:

            @angular/common将位置添加到您的构造函数

            constructor(private _location: Location) {}
            

            添加后退功能:

            back() {
              this._location.back();
            }
            

            然后在你看来:

            <button class="btn" (click)="back()">Back</button>
            

            【讨论】:

            • 这仅适用于您之前在父路由中的情况。父路由与浏览器历史无关...
            • 它导航回来,但不导航到组件的父级
            • 不应该使用这个,如果用户从外部站点访问组件,它将被带回该站点。此代码与单击浏览器中的返回按钮相同
            猜你喜欢
            • 1970-01-01
            • 2022-11-06
            • 1970-01-01
            • 2017-03-28
            • 2019-12-19
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2022-07-24
            相关资源
            最近更新 更多