通过路由路径在Angular中发送数据

378
有没有办法在 router.navigate 中作为参数发送数据? 我的意思是,像这个例子this一样,你可以看到路由有一个数据参数,但是这样做不起作用:
this.router.navigate(["heroes"], {some-data: "othrData"})

因为some-data不是一个有效的参数。我该怎么做?我不想使用queryParams发送该参数。


我认为应该像AngularJS一样采用另一种方式,我们可以做类似于$state.go('heroes', {some-data: "otherData"})的事情。 - Motomine
使用我的方法 https://www.npmjs.com/package/ngx-navigation-with-data,我上一条评论写的,最适合每个人。 - Virendra Yadav
https://dev59.com/XFsX5IYBdhLWcg3wHsdv#69420764 - Billu
2
路由是Angular中的一个复杂功能,绝对值得学习!在这里,您可以找到有关通过路由传递数据的有趣细节: https://indepth.dev/tutorials/angular/indepth-guide-to-passing-data-via-routing 本指南介绍了使用静态数据定义路由和在特定导航期间使用动态数据(状态)的各种技术。 - Maciej Wojcik
10个回答

886

因为有很多不同的方法,所以这个主题存在很多混淆。

以下屏幕截图中使用的是适当的类型:

private route: ActivatedRoute
private router: Router

1) 必填路由参数:

enter image description here

2) 可选路由参数:

enter image description here

3) 路由查询参数:

enter image description here

4) 您可以使用服务在不使用路由参数的情况下传递数据给其他组件。

例如,请参考:https://blogs.msmvps.com/deborahk/build-a-simple-angular-service-to-share-data/

这里有一个此示例的 plunker:https://plnkr.co/edit/KT4JLmpcwGBM2xdZQeI9?p=preview


4
谢谢您的提问!第二和第三种方式有什么区别?因为两者最终都会在 URL 中添加 "?parameter="。您能给我一个第四种方式的例子吗?我搞不清楚如何做。 - Motomine
10
我还有一门关于Angular路由的Pluralsight课程,涵盖了这方面的所有内容:https://app.pluralsight.com/library/courses/angular-routing/table-of-contents 如果你对更多信息感兴趣,可以注册一周的免费试用。 - DeborahK
谢谢!我想我会使用服务,因为我不想显示参数,但在某些情况下,其他用途可能也有效。 - Motomine
3
数据仅在执行应用程序内部“共享”。如果用户刷新页面,则整个应用程序将从服务器重新加载,因此应用程序中不会保留先前的状态。从正常应用程序的角度来考虑,当用户刷新时,就像关闭并重新打开应用程序。如果您需要在刷新后保留状态,则需要将其存储在某个地方,例如本地存储或服务器上。 - DeborahK
4
小提示:route 类型应该是 ActivatedRoute,而不是 Router - Arsen Khachaturyan
显示剩余21条评论

492

Angular 7.2.0引入了一种新的方法。

https://angular.io/api/router/NavigationExtras#state

发送:

    this.router.navigate(['action-selection'], { state: { example: 'bar' } });

接收:

    constructor(private router: Router) {
      console.log(this.router.getCurrentNavigation().extras.state.example); // should log out 'bar'
    }

您可以在此处找到一些其他信息:

https://github.com/angular/angular/pull/27198

上面的链接包含了这个例子,可能会很有用: https://stackblitz.com/edit/angular-bupuzn


40
考虑到 Angular 7 中的新功能,这是正确答案。 - Randy
4
有了这种方法,如果用户进行了浏览器刷新,我该如何处理?在这种情况下,导航附加项中的数据似乎会消失,因此无法在刷新后再次使用它。 - tobi_b
10
是的,这就是为什么你只能在构造函数中通过this.router.getCurrentNavigation()获取数据。 如果你需要在其他地方使用,比如在ngOnInit()内部,你可以通过"history.state"访问数据。 根据文档说明:"传递给任何导航的状态。在导航执行时,此值将通过从router.getCurrentNavigation()返回的extras对象访问。一旦导航完成,当调用location.go或location.replaceState方法以激活此路由之前,此值将写入history.state。" - Véger Lóránd
38
同时,请确保您不要在 ngOnInit() 中尝试接收额外的对象,如 this.router.getCurrentNavigation().extras - hastrb
3
@KinleyChristian 请看一下这个答案,如果您还有疑问,请让我知道!https://dev59.com/vVQI5IYBdhLWcg3w-Qhi#54891361 - Véger Lóránd
显示剩余9条评论

70

最新版本的Angular(7.2+)现在可以使用 NavigationExtras 选项传递额外的信息。

主页组件

import {
  Router,
  NavigationExtras
} from '@angular/router';
const navigationExtras: NavigationExtras = {
  state: {
    transd: 'TRANS001',
    workQueue: false,
    services: 10,
    code: '003'
  }
};
this.router.navigate(['newComponent'], navigationExtras);

新组件

test: string;
constructor(private router: Router) {
  const navigation = this.router.getCurrentNavigation();
  const state = navigation.extras.state as {
    transId: string,
    workQueue: boolean,
    services: number,
    code: string
  };
  this.test = "Transaction Key:" + state.transId + "<br /> Configured:" + state.workQueue + "<br /> Services:" + state.services + "<br /> Code: " + state.code;
}

输出

这里输入图片描述

希望这可以帮助到你!


6
我不断收到“navigation is null”的错误提示。我尝试了几个示例... - AppDreamer
14
这段话的意思是:这是一篇老帖子,但对于未来的访问者——你必须在构造函数中调用它。 - maazadeeb
页面刷新后,您仍然可以访问状态数据吗? - Sofía
好的,我刚刚亲自测试了一下,它在从旧组件直接路由到新组件后完美运行。但是一旦重新加载页面,状态就变成未定义:( - Sofía
这个代码在用户不刷新页面的情况下运行得很完美。但是一旦用户刷新页面,状态就会变成未定义。:( - Piyush

5

我需要访问CustomRouteReuseStrategy中的数据,但由于循环依赖关系,我无法在那里注入Router,但是你可以使用Location对象来读取状态。

Send:

    this.router.navigate(['action-selection'], { state: { example: 'bar' } });

Receive:
    import { Location } from '@angular/common';

    constructor(private location: Location) {
      console.log(this.location.getState().example); // should log out 'bar'
    }

1
这种方法很有效。如果你想完全在模板中使用它,将你的state作为绑定输入提供给与routerLink相同的元素。例如:<button [routerLink]="['action-selection']" [state]="{ example: 'bar' }"> 带有状态导航 </button> - Aaron J

4
自 Angular 15 开始,this.router.getCurrentNavigation() 可能会返回 null,因为组件在导航之后实例化。
另一种选择是从 Location(来自 @angular/common)中访问状态。
  import { Location } from '@angular/common';

  constructor(private location: Location) {
    location.getState() // do what you want 
  }

https://dev59.com/vVQI5IYBdhLWcg3w-Qhi#75150492 - Jnr
https://dev59.com/0sXsa4cB1Zd3GeqPnZoG#75173301 - Jnr

2
在navigateExtra中,我们只能传递特定的名称作为参数,否则会显示以下错误: 例如-在这里我想在路由器导航中传递客户键,并且我像这样传递:
this.Router.navigate(['componentname'],{cuskey: {customerkey:response.key}});

但是它显示了以下错误:

Argument of type '{ cuskey: { customerkey: any; }; }' is not assignable to parameter of type 'NavigationExtras'.
  Object literal may only specify known properties, and 'cuskey' does not exist in type 'NavigationExt## Heading ##ras'

解决方法: 我们需要这样编写代码:
this.Router.navigate(['componentname'],{state: {customerkey:response.key}});

1
@dev-nish,您的代码可以进行一些小调整后正常运行。请加上

标签。
const navigationExtras: NavigationExtras = {
  state: {
    transd: 'TRANS001',
    workQueue: false,
    services: 10,
    code: '003'
  }
};

转换为

let navigationExtras: NavigationExtras = {
  state: {
    transd: '',
    workQueue: ,
    services: ,
    code: ''
  }
};

如果您想特定地发送一种类型的数据,例如JSON作为表单填写的结果,则可以按照之前解释的方式发送数据。

https://dev59.com/XFsX5IYBdhLWcg3wHsdv#69420764 - Billu

1
当发出“NavigationEnd”事件时,使用“this.router.getCurrentNavigation()”获取当前导航状态。如果导航对象的extras属性中存在导航状态,则将其记录到控制台。
constructor(
    private router: Router,
    private activeRoute: ActivatedRoute
  ) {

    this.router.events
      .pipe(
        filter((event) => event instanceof NavigationEnd),
        takeUntil(this.unsubscribe$)
      )
      .subscribe((event) => {
        const navigation = this.router.getCurrentNavigation();
        if (navigation && navigation.extras.state) {
          console.log(navigation.extras.state);
        }
      });
}


  ngOnDestroy(): void {
    this.unsubscribe$.next();
    this.unsubscribe$.complete();
  }

ChatGPT的解释:

  • this.router.events属性表示一个可观察对象,用于发出与路由导航相关的事件。

  • pipe方法允许您将多个操作符链接到可观察对象上。

  • 在这种情况下,filter操作符用于只允许NavigationEnd事件通过。这确保了只有在导航结束时才执行subscribe回调中的代码。

  • takeUntil操作符用于在this.unsubscribe$主题发出值时完成可观察对象。这样做是为了在组件销毁时清理订阅。

  • 最后,在subscribe回调中,使用this.router.getCurrentNavigation()获取当前导航状态。如果有可用的导航状态,并且在extras对象中有一个state属性,则将该状态记录到控制台。

NB:ngOnDestroy方法中,调用this.unsubscribe$.next()方法来发出一个值,并完成this.unsubscribe$主题,进而完成takeUntil操作符并取消订阅路由事件。

优化代码:

this.router.events
  .pipe(
    filter((event) => event instanceof NavigationEnd),
    take(1) // Only take the first event
  )
  .subscribe((event) => {
    const navigation = this.router.getCurrentNavigation();
    if (navigation && navigation.extras.state) {
      console.log(navigation.extras.state);
    }
  });


0
getStateById(stateId) {
        return this.http.get<any>(environment.user_service_url + "/getStateById",
 {params:{"stateId": stateId}});
    }

-15
我在网络上找到的最好解决方法是 ngx-navigation-with-data。 它非常简单易用,能方便地将数据从一个组件导航到另一个组件。 您只需导入该组件类并以非常简单的方式使用即可。 假设您有主页和关于页面,并想发送数据,则

主页组件

import { Component, OnInit } from '@angular/core';
import { NgxNavigationWithDataComponent } from 'ngx-navigation-with-data';

@Component({
 selector: 'app-home',
 templateUrl: './home.component.html',
 styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {

constructor(public navCtrl: NgxNavigationWithDataComponent) { }

 ngOnInit() {
 }

 navigateToABout() {
  this.navCtrl.navigate('about', {name:"virendta"});
 }

}

关于组件

import { Component, OnInit } from '@angular/core';
import { NgxNavigationWithDataComponent } from 'ngx-navigation-with-data';

@Component({
 selector: 'app-about',
 templateUrl: './about.component.html',
 styleUrls: ['./about.component.css']
})
export class AboutComponent implements OnInit {

 constructor(public navCtrl: NgxNavigationWithDataComponent) {
  console.log(this.navCtrl.get('name')); // it will console Virendra
  console.log(this.navCtrl.data); // it will console whole data object here
 }

 ngOnInit() {
 }

}

如有任何疑问,请访问https://www.npmjs.com/package/ngx-navigation-with-data

评论区留言以寻求帮助。


它是以参数的形式传输数据还是在后台传输? - Marium Malik
我无法理解@MariumMalik,请您能否以详细的方式提问? - Virendra Yadav
是的,@MariumMalik。 - Virendra Yadav
15
您似乎是这个内容的作者,而不是“我在互联网上找到的”?您还被要求不要在实现类似功能的 Angular 7 线程(https://github.com/angular/angular/pull/27198)上进行垃圾邮件广告。 - IrishDubGuy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接