【问题标题】:How to get Route data into App Component in Angular 2如何在 Angular 2 中将路由数据获取到应用程序组件中
【发布时间】:2017-09-16 16:25:52
【问题描述】:

我在我的应用路由模块中定义了一些路由数据,如下所示:

    const appRoutes:Routes = [
  {path: '', component: LoginComponent, data:[{PageName:"Login Page"}]}]

我想全局获取数据,这样我就可以使用app.component.ts中的appRoutes来获取URL重定向相关信息如下:

export class AppComponent {
  title = 'Welcome';
  constructor(public router: Router, public authenticationService: AuthenticationService) {
    this.router.events.subscribe(event => {
        console.log("Url",event.urlAfterRedirects);
        console.log("Page Name", router[PageName]); //Not working
      }

我尝试注入 ActivatedRoute,但每次重定向后它都没有更新。

无论如何,我可以在哪里配置页面名称并在全局app.component.ts 中获取它。

【问题讨论】:

    标签: javascript angular typescript angular-routing


    【解决方案1】:

    尝试使用filter 并循环您的事件而不是subscribe

    constructor(router:Router, route:ActivatedRoute) {
        router.events
          .filter(e => e instanceof NavigationEnd)
          .forEach(e => {
            this.title = route.root.firstChild.snapshot.data['PageName'];
        });
    }
    

    请查看以下工作演示:https://plnkr.co/edit/rBToHRaukDlrSKcLGavh?p=info

    【讨论】:

    • 我将上面的代码添加到了我的 app.component.ts 中。我得到的值是未定义的。
    • 你能创建一个 plunker 吗?很难像那样帮助你。正如你看到我的工作演示作品,所以我们非常接近解决你的问题:)
    • 我很抱歉这是一个包含多个模块的大项目,我无法从中创建 plunker。
    • 好的,我明白了 :) 现在我看到我的示例和您的代码之间存在细微差别。在 data 属性的 Routes 数组中,您正在使用数组:data:[{PageName:"Login Page"}] 您可以尝试我的示例与对象:data:{PageName:"Login Page"}。也许为此,您会收到undefined。
    • 这是未来角度的更新答案,stackoverflow.com/questions/60269666/…
    【解决方案2】:

    如果您使用如下所示的 Router 对象进行静态路由:

    {
      path: '',
      pathMatch: 'full',
      component: NameComponent,
      data: { variableName: 'variableValue' }
    },
    

    在 ngOnInit() 上,您可以使用 ActivatedRoute 对象来恢复您从路由器定义中传递的数据:

    ngOnInit() {
      this.localVariable = this.route.snapshot.data['variableName'];
    }
    

    Obs:我正在使用 Angular 5!

    【讨论】:

    • this.route 是什么实例?
    • 你能发一个 stackblitz 链接吗?
    • 迄今为止最好的答案!
    • 这种方法适用于被路由的路由组件中的组件。这种方法不在根应用程序组件本身内起作用。当ngOnInit按请求在根应用组件上调用时,snapshot.data是一个空对象。
    • 只有在使用 root.firstChild 时才对我有用,例如 route.root.firstChild.snapshot.data['variableName']
    【解决方案3】:

    此代码由 Todd Motto(Google 开发专家)编写,用于访问父组件或应用组件中的路由数据。像宝石一样工作。

    import { ActivatedRoute, NavigationEnd, Router } from '@angular/router'
    import { filter, map, mergeMap } from 'rxjs/operators'
    
    constructor(private route: ActivatedRoute, private router: Router) {}
    
    ngOnInit() {
      this.router.events.pipe(
        filter(event => event instanceof NavigationEnd),
        map(() => this.route),
        map(route => {
          while (route.firstChild) route = route.firstChild
          return route
        }),
        filter(route => route.outlet === 'primary'),
        mergeMap(route => route.data)
      ).subscribe(data =>
        console.log('data', data)
      )
    }
    

    见:https://ultimatecourses.com/blog/dynamic-page-titles-angular-2-router-events

    在他的示例中,他使用路由数据来设置应用组件中的页面标题。

    为什么在父节点中访问路线数据如此复杂,我永远不会知道!

    【讨论】:

    • 这看起来很痛苦/令人沮丧。比如,为什么这么难?我自己永远也想不通;(
    • 天哪,它确实有效。这是唯一有效的。我认为这可能是因为从持有插座的父组件访问主插座中的当前路由数据有点复杂,特别是如果您考虑到可能有多个路由器的事实。但这也让我对自己的能力失去了一点信心。我想我会继续努力并继续学习......
    【解决方案4】:

    对于 Angular 5+

    此服务检索当前路线上的数据:(在我的例子中是“标题”)

    import { Injectable } from "@angular/core";
    import { Router, ActivatedRouteSnapshot } from "@angular/router";
    
    @Injectable()
    export class AppRoutingService {
    
      constructor(private router: Router) { }
    
      public getRouteTitle(): string {
        return this.getRouteData("title");
      }
    
      private getRouteData(data: string): any {
        const root = this.router.routerState.snapshot.root;
        return this.lastChild(root).data[0][data];
      }
    
      private lastChild(route: ActivatedRouteSnapshot): ActivatedRouteSnapshot {
        if (route.firstChild) {
          return this.lastChild(route.firstChild);
        } else {
          return route;
        }
      }
    }
    

    组件逻辑:

    import { Component, OnInit, OnDestroy } from "@angular/core";
    import { Router, NavigationEnd } from "@angular/router";
    
    // SERVICES
    import { AppRoutingService } from "../../shared/services/app-routing.service";
    
    @Component()
    export class NavSubmenuComponent implements OnInit, OnDestroy {
      title: string = "";
      routerEvents: any;
    
      constructor(private router: Router, private appRoutingService: AppRoutingService ) { }
    
      ngOnInit() {
        this.title = this.appRoutingService.getRouteTitle();
    
        this.routerEvents = this.router.events
          .filter(event => event instanceof NavigationEnd)
          .subscribe(() => {
            this.title = this.appRoutingService.getRouteTitle();
          });
      }
    
      ngOnDestroy() {
        this.routerEvents.unsubscribe();
      }
    }
    

    【讨论】:

    • RouterService是否应该改为AppRoutingService?
    【解决方案5】:

    在我的情况下,这适用于角度 8:

    每次激活路由时都会自动调用<router-outlet>中的onActivate(outlet)。

    在html中

    <router-outlet (activate)='onActivate(outlet)' #outlet="outlet"></router-outlet>
    

    在组件中

    onActivate(outlet: RouterOutlet) {
        outlet.activatedRoute.data.pipe(map(data => console.log('Router data', data))).toPromise().then();
      }
    

    别忘了导入

    import {RouterOutlet} from '@angular/router';
    import {map} from 'rxjs/operators';
    

    【讨论】:

    • 请解释你的代码是做什么的以及它是怎么做的。
    【解决方案6】:

    根据 Angular 文档,您可以通过这种方式轻松使用它。

    在 Angular 11 上测试。

    https://angular.io/api/router/ActivatedRouteSnapshot#description

    @Component({templateUrl:'./my-component.html'})
    class MyComponent {
      constructor(route: ActivatedRoute) {
        const id: string = route.snapshot.params.id;
        const url: string = route.snapshot.url.join('');
        const user = route.snapshot.data.user;
      }
    }
    

    路线如下:

    {
      path: 'edit/:id',
      component: MyComponent,
      data: {
        user: 1,
        otherData: 'as string'
      }
    }
    

    【讨论】:

    • 先生,那我们如何从 ngOnInit 获取用户值呢?
    【解决方案7】:

    如果您愿意等到 ngAfterViewInit 事件,您可以使用 viewchild 链接到路由器出口。

    即

      @ViewChild('router')
      private routerOutlet: RouterOutlet;
    
      ngAfterViewInit() {
        this.routerOutlet.activateEvents
          .pipe(
            map(() => this.routerOutlet
              .activatedRouteData
            )
          )
        .subscribe((data) => {
            // Code 
        });
      }
    

    &lt;router-outlet #router="outlet"&gt;&lt;/router-outlet&gt;

    【讨论】:

      猜你喜欢
      • 2017-12-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-12
      • 2017-06-12
      • 2017-07-14
      • 2016-11-25
      • 1970-01-01
      相关资源
      最近更新 更多