为什么只有调整屏幕大小才能更新角度应用程序?

时间:2018-12-09 16:22:38

标签: angular rxjs observable angular-components

三天前,我开始使用Angular和Reactive编程,因此对这项技术还是陌生的。

我已经成功实现了Spring Boot后端服务器,该服务器将通过标签向我发送推文。

现在,我试图为通量中收到的每条消息显示我的角度应用程序中列表组件的元素。

我已成功登录控制台搜索结果,但是我的ngFor无法正常工作...我不知道我在哪里缺少良好的习惯。

这是我的角度应用实现

我的响应式Twitter服务:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable, of, BehaviorSubject } from 'rxjs';
import { ITweet } from './model/itweet';

@Injectable({
    providedIn: 'root'
})
export class ReactiveTwitterSpringService {

    tweetSubject = new BehaviorSubject<ITweet>(new ITweet);

    currentTweet = this.tweetSubject.asObservable();

    tweetTag: string;

    baseUrl = 'http://localhost:8081/search';

    search(tag: string) {

        const url = this.baseUrl + '/' + tag.trim().split(' ').join('_');

        return Observable.create(
            observer => {
                const enventSource = new EventSource(url);
                enventSource.onmessage = (message) => {
                    const json = JSON.parse(message.data);
                    console.log(new ITweet(json.tweetData.name, json.tweetData.text, json.tag));
                    this.tweetSubject.next(new ITweet(json.tweetData.name, json.tweetData.text, json.tag));
                    observer.next(new ITweet(json.tweetData.name, json.tweetData.text, json.tag));
                };
                enventSource.onerror = (error) => {
                    if (enventSource.readyState === 0) {
                        console.log('The stream has been closed by the server.');
                        enventSource.close();
                        observer.complete();
                    } else {
                        observer.error('EventSource error: ' + error);
                    }
                };
               return () => enventSource.close();
            }
        );
    }

    constructor() { }
}

我要搜索的组件和结果列表:

import { Component, OnInit } from '@angular/core';
import { BreakPointService } from '../../providers/break-point.service';
import { ReactiveTwitterSpringService } from '../../reactive/reactive-twitter-spring.service';
import { ITweet } from '../../reactive/model/itweet';
import { Subscription } from 'rxjs';

@Component({
    selector: 'app-tweet-list',
    templateUrl: './tweet-list.component.html',
    styleUrls: ['./tweet-list.component.css']
})
export class TweetListComponent implements OnInit {
    list_div_class;
    search_input_class;

    search_results: ITweet[] = new Array();
    subscribe: Subscription = new Subscription();
    constructor(private tweetService: ReactiveTwitterSpringService) { }

    search(tag) {
        this.search_results = new Array();
        this.subscribe.unsubscribe();
        this.subscribe = new Subscription();
        this.subscribe.add(this.tweetService.search(tag).subscribe(tweet => {
            this.search_results.push(tweet);
            console.log(tweet);
        }));
        console.log('array contains ' + this.search_results);
    }

    ngOnInit() {
        BreakPointService.current_css.subscribe(value => {
            console.log('value is ' + value);
            this.setupCss(JSON.parse(value));
        });
    }

    setupCss(value: any): any {
        this.list_div_class = value.list_div_class;
        this.search_input_class = value.search_input_class;
    }
}

与我的组件有关的html模板:

<div class="{{list_div_class}}">
  <input type="text" class="{{search_input_class}}" (keyup.enter)="search(searchInput.value)" #searchInput>
  <ul class="w3-ul">
    <li *ngFor="let tweet of search_results ">
        data
      <app-tweet-detail [detail]="tweet"></app-tweet-detail>
    </li>
  </ul>
</div>

我正在看很多教程,但是我不知道为什么要在控制台上而不是在数组中获取数据?我觉得我以错误的方式使用了可观测对象,但是老实说我不太了解它们。

我在做什么错?以及如何解决?

更新

偶然地我调整了屏幕大小并显示了数据,为什么?

这是我调整大小之前和之后html内容的图像

before

之后

after

谢谢

对于完整项目github repository

1 个答案:

答案 0 :(得分:0)

在Angular中,我们需要通过调用changeDetectorRef.detectChanges()来手动触发更改检测,或者您可以使用可观察到异步的主题/行为主题。

方法1:

constructor(private cdr: ChangeDetectorRef){} 
this.subscribe.add(this.tweetService.search(tag).subscribe(tweet => {
    this.search_results.push(tweet);
    this.search_results = this.search_results.slice();
    this.cdr.detectChanges();
    console.log(tweet);
}));

方法2:

public this.search_results$ = new Subject<any>();
this.subscribe.add(this.tweetService.search(tag).subscribe(tweet => {
    this.search_results.push(tweet);
    this.search_results$.next(this.search_results);
    console.log(tweet);
}));

模板:

<li *ngFor="let tweet of search_results$ | async ">
    data
  <app-tweet-detail [detail]="tweet"></app-tweet-detail>
</li>