【问题标题】:Angular2 component doesn't detect routing parameter updates (Router 3.0)Angular2 组件不检测路由参数更新(Router 3.0)
【发布时间】:2016-10-27 04:34:31
【问题描述】:

我有一个小 Plunk,我正在用它来玩 Angular 2 中当前可用的新路由器 3.0 alpha。它通常运行良好,但问题是一旦我单击一个链接到具有特定 ID 的“详细信息”组件,当我单击具有不同 ID 的不同链接时,它永远不会改变。该组件永远不会被重新实例化,因此它只会显示它在第一次加载时传递的内容。

这是有问题的组件:

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { ContactsService } from './contacts.service';

@Component({
  selector: 'contacts-detail',
  template: `
    <h2>{{contact.name}}</h2>
  `
})
export class ContactsDetailComponent implements OnInit { 

  constructor(private contactsService: ContactsService, private route: ActivatedRoute) {
  }

  ngOnInit() {
    this.contact = this.contactsService.getContact(this.route.snapshot.params.id);
    console.log('Fetching user', this.route.snapshot.params.id);
  }
}

Here is the Plunk 演示问题。单击一个作者姓名,然后单击另一个以查看它不会更改。

【问题讨论】:

    标签: javascript angular angular2-routing angular2-components angular2-router3


    【解决方案1】:

    另一种方法:

    ngOnInit() {
        this.route.params.forEach((params: Params) => {
          let id = +params['id']; 
          this.contact = this.contactsService.getContact(id);
        });
    }
    

    这里从 Observable 中检索路由参数。使用 Observable 优于 Snapshot 的优点是无需再次实例化即可重用组件。看起来这是根据 Angular 2.0 最终文档推荐的方法。

    【讨论】:

      【解决方案2】:

      似乎有多个 lifeCycle 挂钩可用于此目的。我设法使用DoCheck 接口并在组件类中实现关联的ngDoCheck() 方法来获得所需的行为,如下所示。

      import { Component, DoCheck } from '@angular/core';
      import { ActivatedRoute } from '@angular/router';
      import { ContactsService } from './contacts.service';
      
      @Component({
        selector: 'contacts-detail',
        template: `
          <h2>{{contact.name}}</h2>
        `
      })
      export class ContactsDetailComponent implements AfterViewChecked, DoCheck { 
      
        constructor(private contactsService: ContactsService, private route: ActivatedRoute) {
        }
      
        ngDoCheck() {
          this.contact = this.contactsService.getContact(this.route.snapshot.params.id);
        }
      }
      

      Here's a plunk 更新代码。

      不过,我不相信这是最好/正确的生命周期挂钩。也许Router 提供了某种钩子可以更好地解决这个问题。

      【讨论】:

      • 这是一种有趣的方法(而且它显然有效)。从DoCheck 周围的少量文档来看,它似乎是为了与指令一起使用。知道从快照中获取参数值与从可观察者中获取参数值是否有优势吗?
      • @R.Richards 我不确定这是不是正确的事情。我使用与@Input 变量相关联的组件中的表单字段进行了测试,并且在输入字段中的每次击键时都会触发ngDoCheck() 方法,这显然不是我们真正想要的。只是“感觉”应该有更好的东西,但我确实看到一篇文章(不是官方的)提到新路由器希望人们像你在回答中那样处理这种情况......
      • 哇。谢谢@Michael Oryl!我想请你喝杯咖啡。我一直试图让我的组件之一在其值之一发生变化时刷新自己,经过多次尝试后我几乎完全放弃了。我尝试按照您的建议实现 ngDoCheck() 方法,现在它可以正常工作了。中提琴。几个小时的挫败感现在已经结束。
      【解决方案3】:

      在您的ContactsDetailComponent 中,将OnInit 更改为:

      ngOnInit() {
          this.sub = this.route.params.subscribe(params => {
           let id = +params['id']; 
           this.contact = this.contactsService.getContact(id);
         });
        }
      

      在你的 Plunk 中为我工作。

      【讨论】:

      • 这当然对我有用,但看起来很奇怪。不过,如果没有其他办法,我会接受这个。非常感谢您花时间回答。
      • 不奇怪,是组件复用。
      • @TDaver 那么让我改变我的选择;这一点都不明显。我寻找类似 ngOnReload 接口的东西来使用,但什么也没找到。这似乎是一种更 Angular2 的方式来做需要做的事情。
      • @TDaver 看看我对这个问题的回答。它使用ngDoCheck() 来捕获更改。不过,我不知道它是否是要使用的精确生命周期钩子。我希望它会在一个重要的组件中经常触发。在我的回答中插入显示它正在使用中。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-03
      • 1970-01-01
      • 1970-01-01
      • 2017-06-20
      • 1970-01-01
      相关资源
      最近更新 更多