在我的Angular 2路由模板之一(FirstComponent)中,我有一个按钮

first.component.html

<div class="button" click="routeWithData()">Pass data and route</div>

我的目标是:

按钮点击->路由到另一个组件,同时保留数据,而不使用另一个组件作为指令。

这是我试过的…

1号的方法

在同一个视图中,我根据用户交互存储收集相同的数据。

first.component.ts

export class FirstComponent {
     constructor(private _router: Router) { }

     property1: number;
     property2: string;
     property3: TypeXY; // this a class, not a primitive type

    // here some class methods set the properties above

    // DOM events
    routeWithData(){
         // here route
    }
}

通常我会通过

 this._router.navigate(['SecondComponent']);

最终传递数据

 this._router.navigate(['SecondComponent', {p1: this.property1, p2: property2 }]);

而带有参数的链接的定义将是

@RouteConfig([
      // ...
      { path: '/SecondComponent/:p1:p2', name: 'SecondComponent', component: SecondComponent} 
)]

这种方法的问题是,我猜我不能在url中传递复杂的数据(例如property3这样的对象);

2方法

另一种方法是在FirstComponent中包含SecondComponent作为指令。

  <SecondComponent [p3]="property3"></SecondComponent>

然而,我想路由到该组件,不包括它!

第三个方法

我在这里看到的最可行的解决方案是使用一个服务(例如FirstComponentService)来

将数据(_firstComponentService.storeData())存储在FirstComponent的routeWithData()上 在SecondComponent的ngOnInit()中检索数据(_firstComponentService.retrieveData())

虽然这种方法似乎完全可行,但我想知道这是否是实现目标的最简单/最优雅的方法。

一般来说,我想知道我是否错过了在组件之间传递数据的其他潜在方法,特别是在代码量可能较少的情况下


当前回答

现在是2019年,这里的许多答案都有用,这取决于你想做什么。如果你想传递一些URL中不可见的内部状态(params, query),你可以从7.2开始使用state(正如我今天刚刚学到的:))。

从博客(Tomasz Kula) -您导航到....路线

…来自ts: this.router。navigateByUrl('/details', {state: {hello: 'world'}});

…from HTML template: <a routerLink="/details" [state]="{hello: 'world'}">Go</a> .

并在目标组件中拾取它:

constructor(public activatedRoute: ActivatedRoute) {}

  ngOnInit() {
    this.state$ = this.activatedRoute.paramMap
      .pipe(map(() => window.history.state))
  }

有点晚了,但希望这能帮助到刚接触Angular的人。

其他回答

Angular 7.2.0引入了在路由组件之间导航时传递数据的新方法:

@Component({
  template: `<a (click)="navigateWithState()">Go</a>`,
})
export class AppComponent  {
  constructor(public router: Router) {}
  navigateWithState() {
    this.router.navigateByUrl('/123', { state: { hello: 'world' } });
  }
}

Or:

@Component({
  selector: 'my-app',
  template: `
  <a routerLink="/details" [state]="{ hello: 'world' }">Go</a>`,
})
export class AppComponent  {}

要读取状态,你可以在导航结束后访问window.history.state属性:

export class PageComponent implements OnInit {
  state$: Observable<object>;

  constructor(public activatedRoute: ActivatedRoute) {}

  ngOnInit() {
    this.state$ = this.activatedRoute.paramMap
      .pipe(map(() => window.history.state))
  }
}

我认为另一种方法对这个问题不好。 我认为最好的方法是路由器角度的查询参数,有两种方式:

直接传递查询参数

有了这段代码,你可以在html代码中通过参数导航到url:

<a [routerLink]="['customer-service']" [queryParams]="{ serviceId: 99 }"></a>

通过路由器传递查询参数

你必须像这样在构造函数中注入路由器:

constructor(private router:Router){

}

现在用这个短语:

goToPage(pageNum) {
    this.router.navigate(['/product-list'], { queryParams: { serviceId: serviceId} });
}

现在,如果你想从另一个组件的路由器读取,你必须使用ActivatedRoute:

constructor(private activateRouter:ActivatedRouter){

}

并订阅:

  ngOnInit() {
    this.sub = this.route
      .queryParams
      .subscribe(params => {
        // Defaults to 0 if no query param provided.
        this.page = +params['serviceId'] || 0;
      });
  }

一个很好的解决方案是使用canActivate方法实现Guard。在这种情况下,您可以从给定的api获取数据,并让用户访问路由文件中描述的组件。同时,可以设置路由对象的数据属性,并在组件中检索它。

假设你有这样的路由配置:

const routes: Routes = [
    { path: "/:projectName", component: ProjectComponent, canActivate: [ProjectGuard] }
]`

在你的警卫文件中,你可能有:

canActivate(next: ActivatedRouteSnapshot,state: RouterStateSnapshot)
: Observable<boolean> | Promise<boolean> | boolean {
return this.myProjectService.getProject(projectNameFoundElsewhere).pipe(
  map((project) => {
    if (project) {
      next.data = project;
    }
    return !!project;
  }),
);

}`

然后在你的组件中

constructor(private route: ActivatedRoute) {
    this.route.data.subscribe((value) => (this.project = value));
}

这种方式与通过服务传递有点不同,因为服务只要没有取消设置,就会将值保存在behaviorSubject中。通过该防护使当前路由的数据可用。我还没有检查子路由是否保留数据。

在需要将数据传递到另一个Route的场景中,最好和最简单的解决方案是使用{window。localStorage}。此外,不要记得在数据使用结束后从本地存储中删除数据。 我使用ngOnDestroy的destroy()方法来清理这些数据。 这也解决了页面刷新丢失数据的问题。

路线:

{ path: 'foo-route', component: FooComponent, data: { myData: false } },

在组件中访问数据对象一次:

Pipe (take(1))立即取消订阅,因此不存在内存泄漏,也不需要手动取消订阅

constructor(private activatedRoute: ActivatedRoute) { ... }

ngOnInit(): void {
  this.activatedRoute.data.pipe(take(1)).subscribe((data) => {
    console.log(data); // do something with the data
  });
}

记得导入需要的东西

编辑:新的firstValueFrom()可能会更好