[angular] Angular-템플릿에서 * ngIf 대 간단한 함수 호출

이것이 여기에 이미 답변되었지만 죄송하지만 특정 시나리오와 일치하는 항목을 찾을 수 없으므로 여기로갑니다!

우리는 개발 팀에서 각도 템플릿의 함수 호출과 관련하여 토론했습니다. 일반적으로 경험에 따라 이러한 작업을 수행하지 않아야한다는 데 동의합니다. 그러나 우리는 언제 그것이 좋을지 논의하려고 노력했습니다. 시나리오를 알려 드리겠습니다.

다음과 같이 여러 매개 변수를 확인하는 ngIf에 래핑 된 템플릿 블록이 있다고 가정 해 보겠습니다.

<ng-template *ngIf="user && user.name && isAuthorized">
 ...
</ng-template>

다음과 비교할 때 성능에 큰 차이가 있습니까?

주형:

<ng-template *ngIf="userCheck()">
 ...
</ng-template>

타자기 :

userCheck(): boolean {
  return this.user && this.user.name && this.isAuthorized;
}

질문을 요약하기 위해 마지막 옵션에 상당한 성능 비용이 있습니까?

우리는 두 가지 이상의 조건을 확인해야하는 상황에서 두 번째 접근 방식을 선호하지만 온라인에서 많은 기사는 함수 호출이 템플릿에서 항상 나쁘다고 말하지만 실제로이 문제입니까?



답변

또한 가능한 한 템플릿에서 함수 호출을 피하려고 노력했지만 귀하의 질문에 따라 빠른 연구를 수행 할 수있었습니다.

캐싱 userCheck()결과 와 함께 다른 사례를 추가했습니다.

*ngIf="isUserChecked"

...
// .ts
isUserChecked = this.userCheck()

https://stackblitz.com/edit/angular-9qgsm9 에서 데모를 준비했습니다.

놀랍게도 그것은 차이가없는 것처럼 보입니다.

*ngIf="user && user.name && isAuthorized"

*ngIf="userCheck()"

...
// .ts
userCheck(): boolean {
  return this.user && this.user.name && this.isAuthorized;
}

*ngIf="isUserChecked"

...
// .ts
isUserChecked = this.userCheck()

이것은 간단한 속성 검사에 유효한 것처럼 보이지만 어떤 async동작, 예를 들어 API를 기다리는 게터와 관련하여 분명히 차이가 있습니다 .


답변

이것은 꽤 의견이 많은 답변입니다.

이와 같은 기능의 사용은 완벽하게 허용됩니다. 템플릿을 훨씬 명확하게 만들며 오버 헤드가 크게 발생하지 않습니다. JB가 이전에 말했듯이 단위 테스트를위한 훨씬 더 나은 기반을 설정합니다.

또한 템플릿에있는식이 변경 감지 메커니즘에 의해 함수로 평가되므로 템플릿이나 구성 요소 논리에 있는지 여부는 중요하지 않습니다.

함수 내부의 논리를 최소한으로 유지하십시오. 그러나 이러한 기능으로 인해 발생할 수있는 성능 영향에 대해주의를 기울이는 경우 어쨌든 모범 사례로 간주되는 ChangeDetectionStrategyto OnPush를 사용하는 것이 좋습니다. 이를 통해주기마다 함수가 호출되는 것은 아니며 Input변경, 템플릿 내에서 일부 이벤트가 발생 하는 경우에만 해당됩니다 .

(더 이상 다른 이유를 알지 못하기 때문에 etc 사용) .


개인적으로 Observables 패턴을 사용하는 것이 더 좋다고 생각하고 async파이프 를 사용할 수 있으며 새로운 값이 나오면 템플릿이 다시 평가됩니다.

userIsAuthorized$ = combineLatest([
  this.user$,
  this.isAuthorized$
]).pipe(
  map(([ user, authorized ]) => !!user && !!user.name && authorized),
  shareReplay({ refCount: true, bufferSize: 1 })
);

그런 다음 템플릿에서 다음과 같이 사용할 수 있습니다.

<ng-template *ngIf="userIsAuthorized$ | async">
 ...
</ng-template>

또 다른 옵션은 ngOnChanges구성 요소에 대한 모든 종속 변수가 입력이고 특정 템플릿 변수를 계산하는 많은 논리가있는 경우를 사용하는 것입니다 (표시하지 않은 경우).

export class UserComponent implements ngOnChanges {
  userIsAuthorized: boolean = false;

  @Input()
  user?: any;

  @Input()
  isAuthorized?: boolean;

  ngOnChanges(changes: SimpleChanges): void {
    if (changes.user || changes.isAuthorized) {
      this.userIsAuthorized = this.userCheck();
    }
  }

  userCheck(): boolean {
    return this.user && this.user.name && this.isAuthorized || false;
  }
}

다음과 같이 템플릿에서 사용할 수 있습니다.

<ng-template *ngIf="userIsAuthorized">
 ...
</ng-template>


답변

여러 가지 이유로 교장에게 권장되지 않습니다.

userCheck ()를 다시 렌더링해야하는지 여부를 결정하려면 Angular는 userCheck () 표현식을 실행하여 반환 값이 변경되었는지 확인해야합니다.

Angular는 userCheck ()의 ​​반환 값이 변경되었는지 여부를 예측할 수 없으므로 변경 감지가 실행될 때마다 함수를 실행해야합니다.

따라서 변경 감지가 300 회 실행되면 리턴 값이 절대 변경되지 않더라도이 함수를 300 회 호출합니다.

자세한 설명 및 추가 문제 https://medium.com/showpad-engineering/why-you-should-never-use-function-calls-in-angular-template-expressions-e1a50f9c0496

구성 요소가 크거나 많은 변경 이벤트에 참석할 때 발생하는 문제는 구성 요소가 작고 몇 가지 이벤트에만 참석하면 문제가되지 않습니다.

관찰 가능한 예제

user$;
isAuth$
userCheck$;

userCheck$ = user$.pipe(
switchMap((user) => {
    return forkJoin([of(user), isAuth$]);
 }
)
.map(([user, isAuthenticated])=>{
   if(user && user.name && isAuthenticated){
     return true;
   } else {
     return false;
   }
})
);

그런 다음 코드에서 비동기 파이프로 관찰 가능합니다.


답변

개발자가 성능과 관련하여 설명과 함수 호출의 차이점을 알지 못하도록 JavaScript를 목표로 작성했다고 생각합니다.

C ++에는 inline함수를 표시하는 키워드 가 있습니다. 예를 들면 다음과 같습니다.

inline bool userCheck()
{
    return isAuthorized;
}

이것은 함수 호출을 제거하기 위해 수행되었습니다. 결과적으로 컴파일러는 모든 호출을 userCheck함수 본문으로 바꿉니다 . 혁신의 이유 inline? 성능 향상

따라서 하나의 표현식을 가진 함수 호출의 실행 시간은 아마도 expresion의 실행보다 느리다고 생각합니다. 그러나 함수에 하나의 표현 만 있으면 성능의 차이를 느끼지 않을 것이라고 생각합니다.


답변