Angular2生命周期钩子处理本地数据,但不处理api数据

时间:2017-02-17 06:41:59

标签: angular

我制作了以下小程序来显示我的问题。当我使用本地数据填充我的div时,我的largestHeight方法在正确的时间运行得很好,但是当我使用API​​数据时,largestHeight方法运行得太快并且在数据之前完成插入。

这两个组件是整个程序。我在主要组件HTML模板中标记了需要更改的一个变量,以查看两种数据类型之间的差异。 (我试着用这两段代码填充6小时,但最后,我无法让它工作,即使我确信它应该是非常直接的):(

主要组件

import { Component, OnInit, ElementRef, QueryList, ViewChildren, ViewChild, Renderer, AfterViewInit } from '@angular/core';
import { Http } from '@angular/http';
import 'rxjs/Rx';

export interface IHeadlines {
    userId: number;
    id: string;
    title: string;}

export interface GroupPosts {
    title: string;
    posts: IHeadlines[];}

@Component({
  selector: 'test-main3',
  template: `
    <div id="main_container" #main_container>
         <div id="one" #containers>
            <test-child3 [data]="localdata"></test-child3>  <!-- Change "localdata" to "apidata" to see the difference -->
        </div>
        <div id="two" #containers>
            ***** <br>
            *****
        </div>
    </div>
        `,
styles: [`
    #main_container {
          background-color: #cc66ff;
          height:100px;
        }
    #one {
      background-color: #669966;
      position:absolute;
      margin-left: 33.5%;
    }
    #two {
      background-color: #ff99cc;
      position:absolute;
      margin-left: 5%;
    }
  `],
})
export class Main3Component implements OnInit {

  @ViewChildren('containers', {read: ElementRef})
  public divs: QueryList<ElementRef>
  @ViewChild('main_container')
  public mainContainerRef: ElementRef;  
  apidata: IHeadlines[];    

    localdata = [
    { id: 'text1', title: 'up' }, 
    { id: 'text2', title: 'down' }, 
    { id: 'text3', title: 'down' }, 
    { id: 'text4', title: 'up' }, 
    { id: 'text5', title: 'down' }, 
    { id: 'text6', title: 'up' }, 
    { id: 'text7', title: 'up' }, 
    { id: 'text8', title: 'down' }, 
    { id: 'text9', title: 'up' }, 
    { id: 'text10', title: 'down' }
 ];

  constructor(private _http: Http, private _renderer:Renderer) { }

  getPosts() {
    const url = 'https://jsonplaceholder.typicode.com/albums';
    return this._http.get(url)
        .map(x => x.json());
  }

  ngOnInit() { 
        this.getPosts()
            .subscribe(x => this.apidata = x);
    }

  ngAfterViewInit() {
        this.largestHeight();  
    }

  largestHeight()   {
   console.log("Parent ngAfterViewInit");
    let largestHeight = this.divs.reduce((topHeight, divValue) => {
        let currentDiv = divValue.nativeElement.getBoundingClientRect();
        return (currentDiv.height > topHeight ? currentDiv.height : topHeight);
     }, 0);
    this._renderer.setElementStyle(this.mainContainerRef.nativeElement, 'height', largestHeight + 40 + 'px');
    this.divs.forEach((names) => {
    this._renderer.setElementStyle(names.nativeElement, 'height', largestHeight + 'px');
    console.log(largestHeight);
    }); 
   }

}

子组件

import { Component, OnInit, Input, SimpleChanges } from '@angular/core';
import { IHeadlines, GroupPosts } from '../main3.component';

@Component({
  selector: 'test-child3',
   template: `
        <div *ngFor="let headlines of data">    
            {{headlines.id}} {{headlines.title}} <br>
        </div>
        `,
  styles: ['div {color: white;}']
})
export class Child3Component implements OnInit {

 @Input() data: IHeadlines[];
 groupPosts: GroupPosts[];

  constructor() { }

  ngOnInit() {
  }

 ngOnChanges(changes: SimpleChanges) {
       if (changes['data']) {
           this.groupPosts = this.groupByCategory(this.data);
       }
   }

groupByCategory(data: IHeadlines[]): GroupPosts[] {
        if (!data) return
        const categories = new Set(data.map(x => x.title));
                const result = Array.from(categories).map(x => ({
            title: x,
            posts: data.filter(post => post.title === x)
        }));
        return result;
    }    

}

感谢任何人试图提供帮助!

1 个答案:

答案 0 :(得分:2)

我猜你需要在渲染元素后调用largestHeight函数。

你可以这样解决:

import 'rxjs/add/operator/first';
...
constructor(private ngZone: NgZone) { }

ngOnInit() { 
   this.getPosts()
     .subscribe(x => { 
        this.apidata = x;
        this.ngZone.onMicrotaskEmpty.first().subscribe(() => {
          this.largestHeight(); 
        });
      });
}

<强> Plunker Example