Angular 8에서 @ViewChild에 새로운 정적 옵션을 어떻게 사용해야합니까?


204

새로운 Angular 8 뷰 하위를 어떻게 구성해야합니까?

@ViewChild('searchText', {read: ElementRef, static: false})
public searchTextInput: ElementRef;

vs

@ViewChild('searchText', {read: ElementRef, static: true})
public searchTextInput: ElementRef;

어떤게 더 좋아? 언제 static:truevs를 사용해야 static:false합니까?

답변:


237

대부분의 경우을 사용하려고합니다 {static: false}. 이와 같이 설정하면 구조적 지시문과 같은 바인딩 분석에 의존하는 쿼리 일치를 *ngIf, etc...찾을 수 있습니다.

사용시기의 예 static: false:

@Component({
  template: `
    <div *ngIf="showMe" #viewMe>Am I here?</div>
    <button (click)="showMe = !showMe"></button>
  ` 
})
export class ExampleComponent {
  @ViewChild('viewMe', { static: false })
  viewMe?: ElementRef<HTMLElement>; 

  showMe = false;
}

static: false더 각도 9. 읽기의 기본 대체 동작 될 것입니다 여기여기에

{ static: true }옵션은 내장 된 뷰 생성을 지원하기 위해 도입되었습니다. 동적으로 뷰를 생성하고에 액세스하려고 하면 오류 가 발생 TemplateRef하므로이를 수행 할 수 없습니다 . 정적 플래그를 true로 설정하면 ngOnInit에서 뷰가 생성됩니다.ngAfterViewInitExpressionHasChangedAfterChecked

그렇지만:

대부분의 경우 가장 좋은 방법은을 사용하는 것 {static: false}입니다.

알고 생각해야합니다 { static: false }당신이 사용하려는 경우가 아니면 정적 플래그를 설정하면, 더 이상 필요하다는 것을 의미 옵션은 각도 9에 기본을 할 것이다 static: true옵션을 선택합니다.

angular cli ng update명령을 사용 하여 현재 코드베이스를 자동으로 업그레이드 할 수 있습니다 .

마이그레이션 안내서 및 이에 대한 자세한 정보는 여기여기를 확인 하십시오 .

정적 쿼리와 동적 쿼리의 차이점은 무엇입니까?

@ViewChild () 및 @ContentChild () 쿼리에 대한 정적 옵션은 쿼리 결과를 사용할 수있는시기를 결정합니다.

정적 쿼리 (정적 : true)를 사용하면 뷰가 생성 된 후 변경 감지가 실행되기 전에 쿼리가 해결됩니다. 그러나 결과는 ngIf 및 ngFor 블록의 변경과 같은보기 변경 사항을 반영하도록 업데이트되지 않습니다.

동적 쿼리 (정적 : false)를 사용하면 @ViewChild () 및 @ContentChild ()에 대해 ngAfterViewInit () 또는 ngAfterContentInit () 후에 각각 쿼리가 해결됩니다. ngIf 및 ngFor 블록 변경과 같은보기 변경에 대한 결과가 업데이트됩니다.


(출시 후 변경) 각 문서에 대한 링크를 업데이트하시기 바랍니다 angular.io/api/core/ViewChild#description
사친 굽타

2
childView 인스턴스에 액세스 할 수 없습니다. 그것은 항상 정의되지 않았다고 말합니다.
Nesan Mano 2016 년

Angular 9에서 정적 옵션을 제거하는 정보에 대한 링크를 제공 할 수 있습니까?
Alex Marinov

@AlexMarinov 나는 각도 9에서 무슨 일이 일어날 지 더 명확하게하기 위해 대답을 업데이트했습니다. 이것에 대한 링크는 마이그레이션 가이드에 있습니다
Poul Kruijt

1
@ MinhNghĩa 구성 요소 템플릿 외부에 전체 구성 요소를 중첩하면을 사용할 수 { static: true }있지만 내부의 ViewChild에 직접 액세스 할 필요가 없으면을 ngOnInit사용해야합니다 { static: false }.
Poul Kruijt

88

따라서 경험적으로 다음을 수행 할 수 있습니다.

  • { static: true }당신이 액세스 할 때 요구 설정을 할 수 ViewChild있는가 ngOnInit.

  • { static: false }에서만 액세스 할 수 있습니다 ngAfterViewInit. 이것은 또한 *ngIf템플릿의 요소에 구조적 지시어 (예 :)가있을 때 가고 싶은 것입니다 .


2
참고 : Angular 9에서 정적 플래그는 기본적으로 false로 설정되므로 "모든 {static : false} 플래그를 안전하게 제거 할 수 있습니다". 설명서 : angular.io/guide/static-query-migration
Stevethemacguy

17

각도 문서에서

static- 변경 감지가 실행되기 전에 쿼리 결과를 해결할지 여부 (정적 결과 만 반환) 이 옵션을 제공하지 않으면 컴파일러는 쿼리 결과를 사용하여 쿼리 해결 타이밍을 결정하는 기본 동작으로 돌아갑니다. 쿼리 결과가 중첩 된 뷰 안에 있으면 (예 : * ngIf) 변경 감지가 실행 된 후 쿼리가 해결됩니다. 그렇지 않으면 변경 감지가 실행되기 전에 해결됩니다.

static:true아이가 어떤 조건에 의존하지 않는 경우 사용하는 것이 좋습니다 . 요소의 가시성이 변경되면 static:false더 나은 결과를 얻을 수 있습니다.

추신 : 새로운 기능이기 때문에 성능 벤치 마크를 실행해야 할 수도 있습니다.

편집하다

@Massimiliano Sartoretto가 언급했듯이 github commit 은 더 많은 통찰력을 줄 수 있습니다.


3
나는이 기능 뒤에 공식적인 동기를 부여 할 것이다. github.com/angular/angular/pull/28810
Massimiliano Sartoretto

2

Angular 8로 업그레이드 한 후 ngOnInit에서 ViewChild가 null이기 때문에 여기에 왔습니다.

정적 쿼리는 ngOnInit 전에 채워지고 동적 쿼리 (static : false)는 채워집니다. 다시 말해, static : false를 설정 한 후 ngOnInit에서 viewchild가 null 인 경우 static : true로 변경하거나 코드를 ngAfterViewInit로 이동하는 것을 고려해야합니다.

https://github.com/angular/angular/blob/master/packages/core/src/view/view.ts#L332-L336을 참조 하십시오.

다른 답변은 정확하며 그 이유를 설명합니다. ngIf 내부의 ViewChild 참조와 같은 구조적 지시문에 의존하는 쿼리는이 지시문의 조건이 해결 된 후 (예 : 변경 감지 후) 실행되어야합니다. 그러나 static : true를 안전하게 사용하여 중첩되지 않은 참조에 대해 ngOnInit 전에 쿼리를 해결할 수 있습니다. 이 특별한 사례는 null 예외라고 언급하면서 나에게 있었던 것처럼이 특수성을 만날 수있는 첫 번째 방법 일 수 있습니다.


1

자식 @angular 5+ 토큰 두 인수보기 ( 'local reference name', static : false | true)

@ViewChild('nameInput', { static: false }) nameInputRef: ElementRef;

참과 거짓의 차이점을 알고 이것을 확인하십시오.

static-변경 감지가 실행되기 전에 쿼리 결과를 해결할지 여부 (정적 결과 만 반환) 이 옵션을 제공하지 않으면 컴파일러는 쿼리 결과를 사용하여 쿼리 해결 타이밍을 결정하는 기본 동작으로 돌아갑니다. 쿼리 결과가 중첩 된 뷰 안에 있으면 (예 : * ngIf) 변경 감지가 실행 된 후 쿼리가 해결됩니다. 그렇지 않으면 변경 감지가 실행되기 전에 해결됩니다.


0

ng8에서 상위 구성 요소의 하위 구성 요소에 액세스 할시기를 수동으로 설정할 수 있습니다. static을 true로 설정하면 상위 컴포넌트가 onInit후크 의 컴포넌트 정의 만 가져옵니다 . 예 :

 // You got a childComponent which has a ngIf/for tag
ngOnInit(){
  console.log(this.childComponent);
}

ngAfterViewInit(){
  console.log(this.childComponent);
}

static이 false 인 경우 ngAfterViewInit (), ngOnInit ()의 정의 만 정의되지 않습니다.

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