【问题标题】:Angular 6 - Unable to retrieve static dataAngular 6 - 无法检索静态数据
【发布时间】:2018-06-18 15:24:49
【问题描述】:

问题:在路由中定义的静态数据永远不会通过在 ActivatedRoute 订阅数据对象来检索。其他一切似乎都工作正常,数据对象不为空,但我无法从中获取数据。当我尝试从数据对象中调试数据时,它输出“未定义”,当我尝试将其绑定到 UI 时,什么都没有显示,但是当我在 Chrome 中查看 ActivatedRoute 消息时,它有数据。经过多次尝试后,我很确定我的语法应该可以基于许多示例工作,所以 Angular 6 中可能发生了一些变化,或者 Angular 有什么问题?

路线代码:

    const appRoutes: Routes = [
  {
    path: "article",
    redirectTo: "/article/partners",
    pathMatch: "full"
  },
  { 
    path: "article",
    children: [
      {
        path: "bawo",
        component: BawoArticleComponent,
        data: { title: 'BaWo' }
      },
      {
        path: "goldenhands",
        component: GoldenHandsArticleComponent,
        data: { title: 'Golden Hands' }
      },
      {
        path: "investors",
        component: InvestorsArticleComponent,
        data: { title: 'Investors' }
      },
      {
        path: "partners",
        component: PartnersArticleComponent,
        data: { title: 'Partners' }
      }
    ]
  },
  {
    path: "**",
    redirectTo: "/article/partners"
  }
];

检索组件代码(我已经注释了相关代码在哪里):

export class ArticleSelectorComponent implements OnInit {
  arrowFader: string;

  opacity: string;

  fadeTimer: Observable<number>;

  constructor(private router: Router, private activatedRoute: ActivatedRoute) {}

  ngOnInit() {
    this.router.events.subscribe((e: RouterEvent) => {
      this.fadeTimer = timer(0, 150);
      let subscription = this.fadeTimer.subscribe(currentValue => {

        let calc = currentValue & 3;

        if (calc == 0) {
          this.arrowFader = '>';
          this.opacity = '0.5';
        }
        else if (calc == 1) {
          this.arrowFader = '>>';
          this.opacity = '0.65';
        }
        else {
          this.arrowFader = '>>>';
          this.opacity = '0.8';
        }
      });

      this.fadeTimer.subscribe(currentValue => {
        if(currentValue >= 14) {
          subscription.unsubscribe();
          this.opacity = '1.0';
        }
      });
    });

// THIS DOESN'T WORK!!!!
    this.activatedRoute.data.subscribe((data: Data) => {
      console.log(data['title']);
    });
  }

// not relevant, this code is ran with parameter at html buttons
  navToArticle(num: number) {
    let navStr = '';
    switch(num){
      case 1: {
        navStr = '/article/bawo';
        break;
      }
      case 2: {
        navStr = '/article/goldenhands';
        break;
      }
      case 3: {
        navStr = '/article/partners';
        break;
      }
      case 4: {
        navStr = '/article/investors';
        break;
      }
    }

    this.router.navigateByUrl(navStr);
  }
}

AppComponent 的 HTML 代码(带有组件指令):

<div class="site">

    <div class="top">
        <div class="anim-in-left">
            <app-domains></app-domains>
        </div>

        <div class="anim-in-down top-title">
            <h1 class="top-title-text">{{ topTitle }}</h1>
        </div>

        <div class="anim-in-right">
            <app-presence></app-presence>
        </div>
    </div>

    <div class="anim-in-up middle">
        <app-article-selector></app-article-selector>
    </div>
</div>

【问题讨论】:

  • 这个 ArticleSelectorComponent 在您的路由器中链接到哪里?还是纯组件?
  • 控制台有错误吗?
  • @AbineshDevadas 它是 AppComponent 中的一个组件指令
  • @FranklinPious 他们以前出现过,但似乎已经消失了
  • 根据文档尝试访问内部构造函数 - angular.io/api/router/ActivatedRoute

标签: angular typescript angular-routing


【解决方案1】:

试试下面的片段,因为如果你立即订阅激活路由,它只订阅当前组件在路由器配置中注册的路由器数据更改,我刚刚添加了 NavigationEnd 过滤器,因此它不会被所有其他不需要的事件触发满足这个要求。

...    
ngOnInit() {
  ...
  this.title$ = this.router.events.pipe(
    filter((event) => event instanceof NavigationEnd),
    map(_ => this.activatedRoute),
    map((route) => {
      while (route.firstChild) {
        route = route.firstChild;
      }

      return route;
    }),
    mergeMap((route) => route.data),
    map((data) => data.title)
  );
  this.title$.subscribe(title => console.log(title));
  ...
}
...

【讨论】:

【解决方案2】:

我分叉了 Angular 示例并(在一定程度上)复制了您的代码 ->

我发现的唯一区别是组件的激活方式。

  1. ArticleSelectorComponent 只是作为对象导入时,绝不是路由生命周期的一部分。
  2. 当它成为路由生命周期的一部分(作为路由组件)时,它就像一个魅力:D

我没有尝试过@abinesh-devadas 响应,但如果您真的想获得data 元素而不考虑组件生命周期,这看起来是一个更好的解决方案。

【讨论】:

  • 很多很多!
【解决方案3】:

幸运的是,问题已经得到解答:

https://stackoverflow.com/a/46305085/1510754

https://github.com/angular/angular/issues/11812#issuecomment-248820529

基于此,这是一个更完整的答案:

import { Component, OnInit } from '@angular/core';
import { Title } from '@angular/platform-browser';
import { Router, RoutesRecognized } from '@angular/router';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss'],
})

export class AppComponent implements OnInit {

  private baseTitle = 'MySite';

  get title(): string {
    return this.titleService.getTitle();
  }

  constructor(
    private router: Router,
    private titleService: Title,
  ) {
  }

  ngOnInit() {
    this.router.events.subscribe(event => {
      if (event instanceof RoutesRecognized) {
        const route = event.state.root.firstChild;
        let title = this.baseTitle;
        if (route.data['title']) {
          title = route.data['title'] + ' - ' + title;
        }
        this.titleService.setTitle(title);
      }
    });
  }

}

注意:设置&lt;title&gt; 不需要title getter,因为这是通过titleService 完成的。但是您可以使用 getter 来更新 &lt;h1&gt; 等。

【讨论】:

    【解决方案4】:

    下面的代码直到最近都运行良好:

    this.router.events
        .pipe(
            filter((event: any) => event instanceof NavigationEnd),
            map(() => this.activatedRoute),
            map((route) => {
                while (route.firstChild) {
                    route = route.firstChild;
                }
                return route;
            }),
            filter((route) => route.outlet === 'primary'),
            mergeMap((route) => route.data)
        )
        .subscribe((event) => {
                this.titleService.setTitle(event['title']);
                console.log(event);
            }
    

    我认为自从升级到 Angular 6.0。无论我尝试什么,我都会得到undefined

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-07-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-22
      • 1970-01-01
      • 2017-12-20
      • 1970-01-01
      相关资源
      最近更新 更多