【问题标题】:Child route reloading without getting data from parent route子路由重新加载而不从父路由获取数据
【发布时间】:2019-10-21 21:12:24
【问题描述】:

我有一个组件“面板”,它有两个子路线仪表板和假期。 这两个子路由都从父组件服务获取有关其 ngOnInit 的数据。

如果我们以正常方式进行,一切正常,仪表板正在加载数据,但如果我们重新加载子路由,它不会获取父服务数据。

如何解决这个问题?

路由模块:-

{
    path: 'panel',
    component: PanelComponent,
    canActivate: [AuthGuard],
    children: [

        {
            path: 'dashboard',
            component: DashboardComponent,

        },
        {
            path: 'holidays',
            component: HolidaysComponent
        }
    ]
}

panelComponent.ts:-

export class PanelComponent implements OnInit {

constructor(private panelService: PanelService, route: ActivatedRoute, private router: Router) {

}

ngOnInit() {
    this.panelService.getUserProfile().subscribe(
        res => {
            this.panelService.userDetails = res;
            this.router.navigate(['panel/dashboard'])
        },
        err => {
            console.log(err);
        },
    ); 
}

DashboardComponent.ts:-

export class DashboardComponent {
/** dashboard ctor */

private userDetails = {
    name:""
}
constructor(private panelService: PanelService) {

}
ngOnInit() {
    //console.log(this.panelService.userDetails.profileDetails[0].name);
    this.userDetails.name=this.panelService.userDetails.profileDetails[0].name
}

【问题讨论】:

    标签: angular angular7 angular-routing


    【解决方案1】:

    ngOnInit 在创建组件时被调用。可能当您第一次访问问题 URL 时,两个组件都在创建,但是当您重新访问时,仅创建子组件,因为父组件从未被销毁。检查何时为 2 个组件触发 ngOnInitngOnDestroy

    您可能需要重构代码。

    【讨论】:

    • 实际上我有一个来自父组件的 ajax 响应,用于所有子组件。通过服务共享是错误的吗?我该如何处理这种情况?
    • 您可以将对服务的调用放在子组件中(如果需要,缓存响应)-或者您可以在解析器中提出请求-或者尼尔斯的答案看起来很有希望,这在此处记录-@ 987654321@
    【解决方案2】:

    当这些组件被渲染为单个路由时,在组件之间共享数据是很好的。

    一切正常

    在这种情况下你的子组件会在父组件之后渲染, 但有时你需要从子路由刷新然后你需要从子组件调用服务方法本身。

    我认为您需要重构您的子组件,如下所示

    ngOnInit() {
      if(!this.panelService.userDetails) { 
         this.panelService.getUserProfile().subscribe( res => {
            this.panelService.userDetails = res;
          },
          err => {
            console.log(err);
          }); 
      }
      this.userDetails.name = this.panelService.userDetails.profileDetails[0].name;
    }
    

    编辑

    BehaviorSubject 是满足您要求的好方法。但是如果你自己重新加载子路由,你也有可能会丢失behaviorSubject oject 中的数据。

    如果您认为甚至需要刷新子路由的数据,检查来自子组件的数据是更好的方法。(至少在我看来)。

    【讨论】:

    • 在 router.navigate(['panel/dashboard']) 之后,dashboard 的 ngOnit 又可以工作了吗?
    • 您好,您的解决方案运行良好,但我有疑问。重新加载子组件时没有调用父组件服务吗?或者仅仅是因为父母的ajax调用没有完成,所以我没有向孩子获取数据?您的解决方案工作正常,但现在我正在重写所有组件中的代码以检查父组件数据是否存在。这是个好方法吗?
    • 是的,我可以通过 Behavior 主题获得相同的功能,但根据您的意见,如果孩子被父母的数据重新加载,我必须检查数据是否存在?
    【解决方案3】:

    你最好在你的服务中使用BehaviorSubject 并订阅它的 observable,你的服务看起来像:

    export class PanelService {
      private userDetailsSubject = new BehaviorSubject(null);
      userDetails$: Observable<UserDetail> = this.userDetailsSubject.asObservable();
    }
    

    然后改变你的getUserProfile函数

    getUserProfile() {
      return this.http.get(‘uri-to-server-resource’).pipe(
        tap(res => this.userDetailsSubject.next(res))
      );
    }
    

    还有你的PanelComponent

    export class PanelComponent implements OnInit {
    
      constructor(private panelService: PanelService, route: ActivatedRoute, private router: Router) {
      }
    
      ngOnInit() {
        this.panelService
          .getUserProfile().subscribe(
            res => {
              this.router.navigate(['panel/dashboard'])
            },
            err => {
             console.log(err);
            },
        ); 
      }
    

    然后您的DashboardComponent 将订阅服务上的可观察对象

    this.panelService.userDetails$.subscribe(value => this.userDetails = value);
    

    或者直接在你的模板中使用

    {{panelService.userDetails$ | asynchronous}}
    

    【讨论】:

    • 我会试试这个。但是,如果 iam 订阅,这是否会在每个子路由加载时启动 ajax 调用?我确实喜欢上面的方式来避免这种情况
    • 不,您仍然在您的父级调用 getUserProfile 中启动 Ajax 调用,响应是在 BehaviorSubject 上安排的,然后每当孩子订阅 panelService.userDetails$ 时,他们都会收到最新的值跨度>
    • 我不明白您是如何使用“this.userDetailsS​​ubject.next(res);”的这个里面的服务文件?我对该服务的订阅是在 panelComponent.ts 中完成的,并且 res 正在到达那里。
    • 我刚刚尝试过这种方式,但在应用程序的初始渲染时仍然得到空值。你能看看这个问题link这似乎是问题所在。
    • 是的,没错,在异步 HTTP 调用响应之前它将是 null。当您创建BehaviorSubject 时,您为构造函数提供了一个初始值(在上述情况下为null,下一个值将是来自服务器的响应,上面的链接将允许您从解析器中执行相同操作这将在导航到您的父路线之前完成
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-04
    • 2020-09-15
    • 2020-06-15
    • 1970-01-01
    • 2017-08-24
    • 1970-01-01
    相关资源
    最近更新 更多