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


14

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

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

다음과 같이 여러 매개 변수를 확인하는 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;
}

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

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


7
아뇨. 또한 템플릿을보다 읽기 쉽게하고, 조건을보다 쉽게 ​​테스트하고 재사용 할 수있게하고, 가능한 한 읽기 쉽고 효율적으로 처리 할 수있는 도구 (전체 TypeScript 언어)를 더 많이 제공하므로 더욱 깨끗합니다. 그래도 "userCheck"보다 훨씬 명확한 이름을 선택합니다.
JB 니 제트

입력 해 주셔서 감사합니다 :)
Jesper

답변:


8

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

캐싱 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를 기다리는 게터와 관련하여 분명히 차이가 있습니다 .


10

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

이와 같은 기능의 사용은 완벽하게 허용됩니다. 템플릿을 훨씬 명확하게 만들며 오버 헤드가 크게 발생하지 않습니다. 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>

답장을 보내 주셔서 감사합니다. 특정 사례의 경우, 해당 구성 요소가 get 요청을 수행하므로 감지 전략 변경은 옵션이 아니므로 변경은 특정 입력이 아니라 get 요청과 관련이 있습니다. 그럼에도 불구하고 이것은 변화가 입력 변수에 의존하는 미래의 컴포넌트 개발에 매우 ​​유용한 정보입니다
Jesper

1
@Jesper 구성 요소가 가져 오기 요청을 수행하는 경우 이미 Observable스트림을 가지고 있으므로 내가 표시 한 두 번째 옵션의 완벽한 후보가됩니다. 어느 쪽이든, 내가 당신에게 통찰력을 줄 수있어서 기쁘다
Poul Kruijt

6

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

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;
   }
})
);

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


2
안녕하세요, 변수 사용에 대한 제안이 심각하게 잘못되었다는 사실을 알고 싶었습니다. 조합 된 값이 변경 될 때 변수가 업데이트되지 않습니다
nsndvd

1
또한 표현식이 템플릿에 직접 포함되어 있는지 또는 함수에 의해 반환되는지에 관계없이 각 변경 감지시 평가되어야합니다.
JB 니 제트

네, 진정한 미안은 나쁜 습관을 만들지 않기 위해 편집 할 것입니다
anthony willis muñoz

@ anthonywillismuñoz 그래서 이런 상황에 어떻게 접근하겠습니까? * ngIf?에서 여러 개의 읽기 어려운 조건에 따라 생활하십시오.
예스퍼

1
상황에 따라 중간 게시물에 몇 가지 옵션이 있습니다. 그러나 나는 관찰 가능한 것을 사용한다고 생각합니다. 조건을 줄이기 위해 예를 들어 게시물을 편집합니다. 당신이 어디에서 조건을 얻는 지 보여줄 수 있다면.
anthony willis muñoz

0

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

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

inline bool userCheck()
{
    return isAuthorized;
}

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

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

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