angular2父子组件通讯 异步问题

angular2父子组件通讯,可以通过:在父组件的模板中绑定变量,在子组件的属性用 @Input 进行修饰。
现在遇到的问题是:一般变量,可以通过这种方式来通讯,但遇到需要加载其他资源,比如ajax这种异步加装变量的方式,就会导致错误。
父组件:

//html
<div class="modifymember-wrap">
  <addmember [adminData]="admin"></addmember>
</div>
//ts
this.managerService.selectedAdmin.subscribe(data => {
      this.admin = data;
      });

managerService为一个服务,里面的selectedAdmin方法是get(),异步操作。
子组件:

@Input() adminData;
ngOnInit() {
    let admin = adminData;
    console.log('admin');
}
ngAfterViewInit() {
    let admin = adminData;
    console.log('admin');
}

因为是异步操作,当加载网页的时候,子组件会先于父组件加载,导致子组件里的变量admin在没有获取到父组件传递的值之前就已经执行了,导致错误。
这样的问题,需要如何处理?

阅读 7.6k
3 个回答

manager.service.ts

import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import { Observable } from 'rxjs/Rx';
import 'rxjs/add/operator/map';

@Injectable()
export class ManagerService {

    constructor(public http: Http) { }

    getPerson(): Observable<{ id: number; title: string; body: string }>{
        return this.http.get('https://jsonplaceholder.typicode.com/posts/1')
        .map(res => res.json());
    }
}

add-member.component.ts

import {Component, Input, OnChanges, SimpleChanges} from '@angular/core';

@Component({
    selector: 'add-member',
    template: `
        <p>id:{{ adminData?.id}}</p>
    `
})
export class AddMemberComponent implements OnChanges{
 @Input() adminData: { id: number; title: string; body: string };

 ngOnChanges(changes: SimpleChanges) {
   if(changes['adminData'] && changes['adminData'].currentValue) {
     console.dir(changes['adminData'].currentValue);
   }
 }
}

app.component.ts

import { Component, OnInit } from '@angular/core';
import {ManagerService} from "./manager.service";

@Component({
  selector: 'exe-app',
  template: `
   <add-member [adminData]="admin"></add-member>
  `
})
export class AppComponent implements OnInit {
  admin: { id: number; title: string; body: string };

  constructor(private managerService: ManagerService) { }

  ngOnInit() {
    this.managerService.getPerson().subscribe(
      res => this.admin = res
    );
  }
}

可以先看一下这篇文章 Angular 2 AsyncPipe,也可以使用AsyncPipe,但文中提到的问题,要注意一下哈。另外组件生命周期中各个钩子的作用及执行顺序也要去了解一下。

我在子组件中,采用的observable方式:

@Input() adminData;
selectAdminSub = new Subject();
selectAdminSubscriptions: Subscription;
ngOnInit() {
    this.selectAdminSub.debounceTime(200).subscribe(()=> {
      if(this.adminData) {
        console.log("selected admin", this.adminData);
        this.admin = this.adminData;
        this.adminId = this.admin['adminId'];
        this.getMyAdmin(this.adminId);
      }
    })
    this.selectAdminSub.next();
}

getMyAdmin(adminId: string) {
    this.managerService.searchAdmins(adminId).subscribe(data => {
      data.resources.map(item => {
      ……
      })
    })
}

managerService为一个服务,searchAdmins()方法为ajax-get请求。
这种写法设置debounceTime(200),可以正常调用到searchAdmins()方法,使用您给的方法,ngOnChanges()也可以正常调用,但会调用2次,第二次正常,第一次searchAdmins()会报错。

问题:console.log("selected admin", this.adminData),这行代码打印时,会打印2次,在父组件中监测admin值,子组件中监测adminData值,打印顺序如下:
1.子组件adminData值,显示空值,
2.父组件中的admin,显示值。
3.子组件adminData值,显示值。
按照这个顺序,第一次子组件里的adminData没有值,这时直接调用searchAdmins()方法会报错。

有时,从父组件传值(比如变量a)给子组件,在子组件的ngOnInit()里直接打印这个变量a,会显示空值,但在子组件的html里调用a,是正常的。

新手上路,请多包涵

我也遇到这个问题,我研究了下生命周期,子组件会检测input变量并输出视图,所以该变量直接输出到子组件视图是没有问题,他会在等待父组件异步后刷新。但如果你有值直接在子组件的ngInit中处理肯定不行,初始它是先加载的,这是你要把逻辑写在子组件的ngOngchanges中等待父组件异步传数据

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进