programing

각도 2 - 모델 변경 후 뷰가 업데이트되지 않음

linuxpc 2023. 5. 21. 11:01
반응형

각도 2 - 모델 변경 후 뷰가 업데이트되지 않음

몇 초마다 REST api를 호출하고 JSON 데이터를 다시 받는 간단한 구성 요소가 있습니다.반환되는 JSON 데이터가 변경되고 있고 모델이 업데이트되고 있지만 보기는 변경되지 않고 있다는 것을 로그 문과 네트워크 트래픽을 통해 알 수 있습니다.

내 구성 요소는 다음과 같습니다.

import {Component, OnInit} from 'angular2/core';
import {RecentDetectionService} from '../services/recentdetection.service';
import {RecentDetection} from '../model/recentdetection';
import {Observable} from 'rxjs/Rx';

@Component({
    selector: 'recent-detections',
    templateUrl: '/app/components/recentdetection.template.html',
    providers: [RecentDetectionService]
})



export class RecentDetectionComponent implements OnInit {

    recentDetections: Array<RecentDetection>;

    constructor(private recentDetectionService: RecentDetectionService) {
        this.recentDetections = new Array<RecentDetection>();
    }

    getRecentDetections(): void {
        this.recentDetectionService.getJsonFromApi()
            .subscribe(recent => { this.recentDetections = recent;
             console.log(this.recentDetections[0].macAddress) });
    }

    ngOnInit() {
        this.getRecentDetections();
        let timer = Observable.timer(2000, 5000);
        timer.subscribe(() => this.getRecentDetections());
    }
}

제 견해는 다음과 같습니다.

<div class="panel panel-default">
    <!-- Default panel contents -->
    <div class="panel-heading"><h3>Recently detected</h3></div>
    <div class="panel-body">
        <p>Recently detected devices</p>
    </div>

    <!-- Table -->
    <table class="table" style="table-layout: fixed;  word-wrap: break-word;">
        <thead>
            <tr>
                <th>Id</th>
                <th>Vendor</th>
                <th>Time</th>
                <th>Mac</th>
            </tr>
        </thead>
        <tbody  >
            <tr *ngFor="#detected of recentDetections">
                <td>{{detected.broadcastId}}</td>
                <td>{{detected.vendor}}</td>
                <td>{{detected.timeStamp | date:'yyyy-MM-dd HH:mm:ss'}}</td>
                <td>{{detected.macAddress}}</td>
            </tr>
        </tbody>
    </table>
</div>

의 결과를 보면 알 수 있습니다.console.log(this.recentDetections[0].macAddress)최근 탐지 개체가 업데이트되고 있지만 페이지를 다시 로드하지 않는 한 보기의 테이블이 변경되지 않습니다.

제가 여기서 뭘 잘못하고 있는지 보려고 애쓰고 있습니다.누가 도와줄 수 있습니까?

당신의 서비스에 있는 코드가 어떻게든 Angular의 영역을 벗어날 수 있습니다.이렇게 하면 변경 탐지가 중단됩니다.이렇게 하면 됩니다.

import {Component, OnInit, NgZone} from 'angular2/core';

export class RecentDetectionComponent implements OnInit {

    recentDetections: Array<RecentDetection>;

    constructor(private zone:NgZone, // <== added
        private recentDetectionService: RecentDetectionService) {
        this.recentDetections = new Array<RecentDetection>();
    }

    getRecentDetections(): void {
        this.recentDetectionService.getJsonFromApi()
            .subscribe(recent => { 
                 this.zone.run(() => { // <== added
                     this.recentDetections = recent;
                     console.log(this.recentDetections[0].macAddress) 
                 });
        });
    }

    ngOnInit() {
        this.getRecentDetections();
        let timer = Observable.timer(2000, 5000);
        timer.subscribe(() => this.getRecentDetections());
    }
}

변경 감지를 호출하는 다른 방법은 각도에서 수동으로 변경 감지 트리거를 참조하십시오.

변경 감지를 호출하는 다른 방법은 다음과 같습니다.

ChangeDetectorRef.detectChanges()

현재 구성 요소 및 하위 구성 요소에 대해 변경 탐지를 즉시 실행합니다.

ChangeDetectorRef.markForCheck()

다음 번 각도 실행 시 현재 구성 요소를 포함하는 변경 감지

ApplicationRef.tick()

전체 응용 프로그램에 대해 변경 탐지 실행

원래는 @Mark Rajcok의 댓글에 있는 답변이지만 ChangeDetectorRef를 사용하여 테스트되고 솔루션으로 작동한 것으로 여기에 배치하고 싶습니다. 여기에 좋은 점이 있습니다.

다른 대안은 주사하는 것입니다.ChangeDetectorRef와 콜cdRef.detectChanges()대신에zone.run()이는 다음과 같은 전체 구성 요소 트리에 대해 변경 감지를 실행하지 않기 때문에 더 효율적일 수 있습니다.zone.run()합니다. – 마크 라즈콕

코드는 다음과 같아야 합니다.

import {Component, OnInit, ChangeDetectorRef} from 'angular2/core';

export class RecentDetectionComponent implements OnInit {

    recentDetections: Array<RecentDetection>;

    constructor(private cdRef: ChangeDetectorRef, // <== added
                private recentDetectionService: RecentDetectionService) {
        this.recentDetections = new Array<RecentDetection>();
    }

    getRecentDetections(): void {
        this.recentDetectionService.getJsonFromApi()
            .subscribe(recent => {
                this.recentDetections = recent;
                console.log(this.recentDetections[0].macAddress);
                this.cdRef.detectChanges(); // <== added
            });
    }

    ngOnInit() {
        this.getRecentDetections();
        let timer = Observable.timer(2000, 5000);
        timer.subscribe(() => this.getRecentDetections());
    }
} 

편집: 사용.detectChanges()구독자 내부에서 문제가 발생할 수 있습니다. 삭제된 보기 사용 시도: 변경 사항 탐지

그것을 해결하기 위해 당신은 해야 합니다.unsubscribe구성 요소를 파괴하기 전에 전체 코드는 다음과 같습니다.

import {Component, OnInit, ChangeDetectorRef, OnDestroy} from 'angular2/core';

export class RecentDetectionComponent implements OnInit, OnDestroy {

    recentDetections: Array<RecentDetection>;
    private timerObserver: Subscription;

    constructor(private cdRef: ChangeDetectorRef, // <== added
                private recentDetectionService: RecentDetectionService) {
        this.recentDetections = new Array<RecentDetection>();
    }

    getRecentDetections(): void {
        this.recentDetectionService.getJsonFromApi()
            .subscribe(recent => {
                this.recentDetections = recent;
                console.log(this.recentDetections[0].macAddress);
                this.cdRef.detectChanges(); // <== added
            });
    }

    ngOnInit() {
        this.getRecentDetections();
        let timer = Observable.timer(2000, 5000);
        this.timerObserver = timer.subscribe(() => this.getRecentDetections());
    }

    ngOnDestroy() {
        this.timerObserver.unsubscribe();
    }

}

저는 이것이 오래된 질문이라는 것을 알지만 저는 제 상황을 공유하고 싶었습니다.저는 팀에서 일하고 있고 누군가는 기본적으로 자동 변경 감지를 비활성화하는 Push에 변경 감지 전략을 설정했습니다.이게 다른 도움이 될지는 모르겠지만 만약을 대비해서요.

@Component({
  selector: 'app-header',
  templateUrl: './header.component.html',
  styleUrls: ['./header.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush
})

https://angular.io/api/core/ChangeDetectionStrategy

저 같은 경우에도 비슷한 문제가 있었습니다.상위 구성 요소에서 호출하는 함수 내부에서 보기를 업데이트하는 중이었고, 상위 구성 요소에서 @ViewChild(NameOfMyChildComponent)를 사용하는 것을 잊었습니다.나는 이 어리석은 실수 때문에 적어도 3시간을 잃었습니다. 즉, 는 그 어떤 방법도 사용할 필요가 없었습니다.

  • 디텍터를 변경합니다. 디텍터를 변경합니다()
  • Detector Ref.
  • ApplicationRef.tick()

영역 및 변경 감지를 처리하는 대신 AsyncPipe가 복잡성을 처리하도록 합니다.이렇게 하면 관찰 가능한 구독, 구독 취소(메모리 누수 방지) 및 Angular 숄더에서 변경 감지가 수행됩니다.

새 요청의 결과를 내보내는 관찰 가능한 클래스로 변경합니다.

export class RecentDetectionComponent implements OnInit {

    recentDetections$: Observable<Array<RecentDetection>>;

    constructor(private recentDetectionService: RecentDetectionService) {
    }

    ngOnInit() {
        this.recentDetections$ = Observable.interval(5000)
            .exhaustMap(() => this.recentDetectionService.getJsonFromApi())
            .do(recent => console.log(recent[0].macAddress));
    }
}

AsyncPipe를 사용하도록 보기를 업데이트합니다.

<tr *ngFor="let detected of recentDetections$ | async">
    ...
</tr>

덧붙이고 싶은 것은, 다음과 같은 방법으로 서비스를 만드는 것이 더 낫다는 것입니다.interval다음과 같이 지정합니다.

  • 요청 (「 」를 )exhaustMap위의 코드에서와 같이);
  • 요청 오류 처리
  • 오프라인 상태일 때 브라우저가 새 요청을 하지 못하도록 합니다.

언급URL : https://stackoverflow.com/questions/36919399/angular-2-view-not-updating-after-model-changes

반응형