Angular 2에서 구성 요소를 다시 렌더링하는 방법은 무엇입니까?


181

Angular 2에서 구성 요소를 다시 렌더링하는 방법은 무엇입니까? Redux로 작업하는 디버그 목적으로 구성 요소가 다시 렌더링되도록 강제하고 싶습니다. 가능합니까?


"다시 렌더링"은 무슨 뜻입니까? 바인딩을 업데이트 하시겠습니까?
Günter Zöchbauer

재 렌더링을 강제해야하는 이유에 대한 간단한 질문입니까?
Tuong Le

답변:


217

변경 감지 후 렌더링이 수행됩니다. 변경된 구성 요소 속성 값이 DOM으로 전파되도록 변경 감지를 강제 실행하려면 (브라우저가 해당 변경 사항을보기에서 렌더링 함) 다음과 같은 옵션이 있습니다.

  • ApplicationRef.tick () -Angular 1과 유사합니다. $rootScope.$digest()즉, 전체 컴포넌트 트리를 확인하십시오
  • NgZone.run (콜백) - 유사 $rootScope.$apply(callback)- 즉, 각 2 구역 내부의 콜백 함수를 평가합니다. 나는 이것이 콜백 함수를 실행 한 후 전체 구성 요소 트리를 확인하게된다고 확신하지는 않습니다.
  • ChangeDetectorRef.detectChanges () -비슷한 $scope.$digest()-즉,이 구성 요소와 그 하위 만 확인

당신은 가져 주입 한 후해야합니다 ApplicationRef, NgZone또는 ChangeDetectorRef구성 요소에.

특정 시나리오의 경우 단일 구성 요소 만 변경된 경우 마지막 옵션을 사용하는 것이 좋습니다.


1
angular2의 최종 버전에 대한 ChangeDetectorRef의 작동 코드가 있습니까? 이제 http의 게시 요청 후 새 사용자를 만든 다음 새 개체를 기존의 기존 사용자 목록으로 밀어 넣은 후 (보기에서 반복되는)보기가 업데이트되지 않는 상황에 직면하고 있습니다. 아주 이상합니다 this is the first time I am facing an update not working in ng2. 변경 감지 전략이 기본값이므로 변경 감지 전략을 망쳐 놓지 않았습니다.
Gary

1
@Gary, 새 질문을 게시하고 구성 요소와 서비스 코드를 포함해야합니다 (이상적으로 문제를 시연하는 최소한의 플 런커 포함). 내가 본 일반적인 문제 this는 POST 콜백에서 올바른 컨텍스트를 사용하지 않는 것 입니다.
Mark Rajcok

변경을 수행 할 때마다 파이프를 수동으로 트리거 할 수 있는지 알고 있습니까? 변경 감지를 트리거하려고 시도했지만 파이프가 업데이트되지 않습니다 ... 파이프에서도 시도했습니다 pure:false. 작동하지만 사용 사례에 비해 너무 비쌉니다 (비효율적).
ncohen

1
@ ncohen, 파이프 업데이트를 수동으로 트리거하는 방법을 모르겠습니다. 순수한 파이프를 사용하고 업데이트를 트리거 할 때마다 객체 참조를 변경할 수 있습니다. 이것에 대해서는 Pipes doc 의 "Pure Pipes"섹션에서 설명합니다 . 사용 사례에 따라 파이프 대신 구성 요소 속성을 사용할 수 있습니다. 이 기술은 파이프 문서 끝에서 간단히 설명합니다.
마크 Rajcok

1
@ N-ate, 모든 링크가 고정되었습니다.
Mark Rajcok

47

tx, 내가 필요한 해결 방법을 찾았습니다.

  constructor(private zone:NgZone) {
    // enable to for time travel
    this.appStore.subscribe((state) => {
        this.zone.run(() => {
            console.log('enabled time travel');
        });
    });

zone.run을 실행하면 구성 요소가 다시 렌더링됩니다.


6
이 컨텍스트에서 appStore는 무엇입니까-어떤 종류의 변수와 유형입니까? 관찰 가능하지만 내 관찰 가능은 버튼 클릭 한 번으로 새로 고치려는 구성 요소 안에 있습니다 ... 그리고 부모 / 현재 위치에서 하위 구성 요소 방법 / 변수에 액세스하는 방법을 모릅니다
Abdeali Chandanwala

28

ChangeDetectorRef 접근 방식

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

export class MyComponent {

    constructor(private cdr: ChangeDetectorRef) { }

    selected(item: any) {
        if (item == 'Department')
            this.isDepartment = true;
        else
            this.isDepartment = false;
        this.cdr.detectChanges();
    }

}

14

* ngIf를 사용하여 구성 요소를 강제로 다시로드합니다.

컨테이너 내부의 모든 구성 요소는 전체 수명주기 후크로 돌아갑니다.

템플릿에서 :

<ng-container *ngIf="_reload">
    components here 
</ng-container>

그런 다음 ts 파일에서 :

public _reload = true;

private reload() {
    setTimeout(() => this._reload = false);
    setTimeout(() => this._reload = true);
}

@loonis 감사합니다! 나는 이것이 작동하는 것처럼 느꼈고를 제외한 모든 것을 가지고있었습니다 setTimeout(). 이제는 간단하고 가벼운 솔루션으로 작업하고 있습니다!
LHM

내가이 10000+ 번을 공표 할 수 있다면 ..
Yazan Khalaileh

주 1 일 - 사라지고 및 크기 변화를 일으킬 수 있습니다 다시 나타나지 및 페이지가 깜박일 수있는 용기
고쉬을

9

다른 답변은 구성 요소의 뷰를 업데이트하는 변경 감지주기를 트리거하는 솔루션을 제공합니다 (전체 다시 렌더링과 동일하지 않음).

전체 사용하여 수행 할 수 있습니다 파괴하고 구성 요소 (보기 모든 라이프 사이클 후크를 호출하고 재건을) 다시 초기화 것이다, 재 렌더링 ng-template, ng-containerViewContainerRef다음과 같은 방법으로 :

<div>
  <ng-container #outlet >
  </ng-container>
</div>

<ng-template #content>
  <child></child>
</ng-template>

다음 구성 요소 모두에 대한 참조를 가지고 #outlet#content우리는 출구 '내용을 취소하고 하위 구성 요소의 다른 인스턴스를 삽입 할 수 있습니다 :

@ViewChild("outlet", {read: ViewContainerRef}) outletRef: ViewContainerRef;
@ViewChild("content", {read: TemplateRef}) contentRef: TemplateRef<any>;

private rerender() {
    this.outletRef.clear();
    this.outletRef.createEmbeddedView(this.contentRef);
}

또한 초기 내용은 AfterContentInit후크에 삽입해야합니다 .

ngAfterContentInit() {
    this.outletRef.createEmbeddedView(this.contentRef);
}

전체 작업 솔루션은 https://stackblitz.com/edit/angular-component-rerender 에서 찾을 수 있습니다 .


1

ChangeDetectorRef.detectChanges()일반적으로 가장 집중적 인 방법입니다. ApplicationRef.tick()일반적으로 슬레지 해머 접근 방식이 너무 많습니다.

을 사용하려면 ChangeDetectorRef.detectChanges()구성 요소 상단에이 항목이 필요합니다.

import {  ChangeDetectorRef } from '@angular/core';

... 일반적으로 생성자에 다음과 같이 삽입하면 별칭이 지정됩니다.

constructor( private cdr: ChangeDetectorRef ) { ... }

그런 다음 적절한 장소에서 에서 다음과 같이 호출합니다.

this.cdr.detectChanges();

당신이 전화하는 ChangeDetectorRef.detectChanges() 은 매우 중요 할 수 있습니다. 당신은 할 필요가 완전히 라이프 사이클을 이해하고 정확히 응용 프로그램 기능 및 해당 구성 요소를 렌더링하는 방법. 숙제를 완전히하고 Angular 라이프 사이클을 이해하는 것을 대체 할 수있는 것은 없습니다. 그런 다음, 일단 이해하면 ChangeDetectorRef.detectChanges()적절하게 사용할 수 있습니다 (때로는 사용 위치를 이해하기가 쉽고 때로는 복잡 할 수도 있음).

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.