Angular2-템플릿에서 개인 변수에 액세스 할 수 있어야합니까?


143

private컴포넌트 클래스에서 변수가 선언 된 경우 해당 컴포넌트의 템플리트에서 변수 에 액세스 할 수 있어야합니까?

@Component({
  selector: 'my-app',
  template: `
    <div>
      <h2>{{title}}</h2>
      <h2>Hello {{userName}}</h2> // I am getting this name
    </div>
  `,
})
export class App {
  public title = 'Angular 2';
  private userName = "Test Name"; //declared as private
}

답변:


226

아니요, 템플릿에서 개인 변수를 사용해서는 안됩니다.

drewmoore의 답변을 좋아하고 그 안에 완벽한 개념적 논리가 있지만 구현 측면에서는 잘못되었습니다. 템플리트는 컴포넌트 클래스 내에 존재하지 않지만 템플리트 외부에 존재합니다. 증명 을 위해이 레포 를 살펴보십시오 .

이것이 작동하는 유일한 이유는 TypeScript의 private키워드가 실제로 멤버를 비공개로 만들지 않기 때문 입니다. JIT (Just-In-Time) 컴파일은 런타임시 브라우저에서 발생하며 JS에는 비공개 멤버 개념이 없습니다 (아직?). 크레딧이 Sander Elias에게로 갑니다 .

으로 ngc당신이 템플릿에서 구성 요소의 전용 멤버를 액세스하려고 경우 앞서-의 타임 컴파일, 당신은 오류를 얻을 수 있습니다. 데모 저장소를 복제하고 MyComponent멤버의 가시성을 비공개로 변경 하면 실행할 때 컴파일 오류가 발생합니다 ngc. 다음은 Ahead-of-Time 컴파일 전용 답변 입니다.


6
이것은 가장 좋은 의견이며 imo는 받아 들여질만한 답변이어야합니다. 일단 변환 된 개인 변수를 사용할 수있는 것은 아닙니다. 코드를 깨끗하게 유지하십시오!
Sam Vloeberghs

2
이것은 유일하게 유효한 답변입니다! 이제 템플릿에서 private var를 사용할 때 Codelyzer가 경고합니다.
maxime1992

7
이것에 대한 나의 유일한 문제는 @Inputs 및 Outputs와 같은 실제 공개 노출 멤버를 외부 세계가 아닌 템플릿에만 노출하려는 멤버로 어떻게 구별하는 것입니다. 템플릿에 액세스 할 수 있지만 다른 컴포넌트에는 액세스 할 수없는 메소드 / 멤버를 원하는 재사용 가능한 컴포넌트를 빌드하는 경우 나는 원래의 대답이 맞다고 생각합니다. 템플릿은 구성 요소의 일부입니다.
Ashg

1
wrt 입력 및 출력뿐만 아니라 @Ashg에 동의합니다. 예를 들어 부모 구성 요소를 자식 구성 요소에 주입하여 구성 요소 간에 통신하려는 경우는 어떻습니까? 그러면 자식 구성 요소는 부모가 외부 세계에 노출하려는 메서드 대신 부모가 템플릿에 노출하는 모든 것을 볼 수 있습니다. Angular의 제약 내 에서이 답변은 올바른 답변이지만 여전히이 디자인을 잘 생각하지는 못했습니다.
Dan King

이것은 Angular의 AoT 컴파일 내 제한 사항과 해결 방법을 다루기 때문에 좋은 대답입니다. 그러나 IMO의 문제는 개념적으로 (의도적으로) 아니었다. 개념적으로 템플릿은 클래스 정의의 일부입니다. 템플릿은 클래스를 확장하거나 상속하지 않으며 인스턴스화 된 객체에 외부 적으로 액세스하지 않습니다. 템플릿은 클래스 자체에서 정의되므로 개념적으로 클래스의 일부이며 개념적으로 개인 멤버에게 액세스 할 수 있어야합니다.
A-Diddy

85

편집 :이 답변은 이제 잘못되었습니다. 내가 올릴 때 주제에 대한 공식적인 지침은 없었지만 @Yaroslov의 (우수하고 정확한) 답변에서 설명했듯이 더 이상 그렇지 않습니다 .Codelizer가 경고하고 구성 요소 템플릿의 개인 변수에 대한 참조에서 AoT 컴파일이 실패합니다 . 즉, 개념적 수준에서는 여기의 모든 것이 유효하게 유지되므로 도움이 된 것처럼이 답변을 남겨 두겠습니다.


그렇습니다.

있다는 사실을 숙지 private구성 요소 / 컨트롤러 / 템플릿 타이프 라이터가 모르는 각 구조 인 반면 다른 액세스 수식, 타이프 라이터 구조이며. 액세스 수정 가시성 제어 사이의 필드 만들기 : 클래스를 private방지 다른 클래스 에 대한 액세스 권한을 필요로하지만, 템플릿 및 컨트롤러가 존재하는 것들 내에서 클래스.

그것은 기술적으로 사실이 아니지만 (클래스가 데코레이터 및 메타 데이터와 관련되는 방법을 이해하는 대신)이 방법으로 생각하면 도움이 될 수 있습니다 .IMHO (중요한 것)는 템플릿과 컨트롤러에 대한 생각에서 분리 된 것으로 이동하기 때문입니다. 엔티티를 컴포넌트 구성의 통합 된 부분으로 생각합니다. 이것은 ng2 정신 모델의 주요 측면 중 하나입니다.

그런 식으로 생각 private하면 컴포넌트 클래스의 변수가 템플릿에 표시 될 것으로 예상됩니다. 같은 이유로 private해당 클래스 의 메소드에 변수가 표시 될 것으로 예상됩니다 .


3
먼저, 나는 당신이 drewmoore처럼 생각했습니다. 그러나 tslint를 4.02로 업그레이드하고 codelyzer를 2.0.0-beta.1로 업그레이드했으며 변수를 볼 때 개인을 사용할 수 없다는 오류가 발생했습니다. @Yaroslav의 대답이 더 적절 해 보입니다.
maxime1992

8
구성 요소 모델이 개인 변수를 볼 수 없다는 것은 합리적이지 않다는 데 동의합니다. 컴파일 중에 동일한 클래스로 으깬해야합니다. 즉, 구성 요소 별 특성, 객체 및 함수를 다른 모든 구성 요소를 사용하여 템플릿에있는 구성 요소를 사용할 수 있습니다. 외부 조정이나 해당 구성 요소에 대한 호출은 완성 된 구성 요소에 예기치 않은 동작을 일으킬 수 있습니다.
Felype

1
@drewmoore, 안녕하세요 몇 달 동안 만 각도를 코딩했습니다. 나는이 문제에 직면했다. 이것에 대한 추가 토론이 있습니까? 따라야 할 패턴에 대한 구체적인 내용을 찾지 못했습니다. imo, 그것이 가치가 있기 때문에 코드 분리를 위반하는 것 같습니다.
Edgar

2
@drewmoore, 나는 당신의 anser 논리에 전적으로 동의한다고 말해야합니다. Angular 팀이 약간 엉망인 것 같습니다. AOT 모드에서는 개인 구성원을 허용하지 않지만 다른 주장하는 문서에서는 개인 구성원의 경우 포인트를 절대적으로 강화 하고이 주제에 혼란을 더하는 것입니다. Docs : "Angular는 컴포넌트의 템플릿을 컴포넌트에 속하는 것으로 간주합니다. 컴포넌트와 해당 템플릿은 서로를 암시 적으로 신뢰합니다. 따라서 컴포넌트 자체 템플릿은 * @ * Input 데코레이터를 사용하거나 사용하지 않고 해당 컴포넌트의 모든 속성에 바인딩 할 수 있습니다. "
Orel Eraki

@drewmoore, 문서 링크 : angular.io/guide/attribute-directives#appendix-why-add-input (주로 입력 데코레이터에 중점을두고 있지만 많은 사람들이 이야기하는 내용은 단지 관련이 없습니다. it)
Orel Eraki

16

코드 예제에서 TypeScript에 대한 질문이 있음에도 불구하고 꼬리표. Dart에서도 Angular2를 사용할 수 있으며 이는 Dart와의 현저한 차이점입니다.

에서는 다트 템플릿 전용 변수 참조 할 수 다트 타이프 달리 효과적으로 외부 전용 부재 액세스를 방지하기 때문에, 컴포넌트 클래스의이.

나는 여전히 컴포넌트에 대해 생각하기 위해 @drewmoores 제안을 뒷받침하지만 템플릿은 하나의 단위로 사용됩니다.

업데이트 (TS) Angular2 TS에서도 개인 속성에 대한 오프라인 컴파일 액세스가 더 제한 될 것으로 보입니다 https://github.com/angular/angular/issues/11422


2
뷰에 액세스 할 수있는 개인 변수를 제한하기 위해 Typescript 컴파일러를 사용할 수 있습니까?
Matthew Harwood

모르겠어요 나는 그렇지 않다고 생각한다.
Günter Zöchbauer

2
개인적으로 사용하면 구성 요소가 얼마나 테스트 가능한지에 영향을 줄 수 있다고 생각합니까? 예를 들어 테스트 컨텍스트에서 구성 요소를 만들면 템플릿 / 클래스 상호 작용이 작동하는지 확인하기 위해 테스트에서 해당 개인 메서드를 호출 할 수 없습니다. 나는 이것을 아직 시도하지 않았으므로 이것이 분명하다면 용서하십시오 :)
Sam Storie

Dart에서는 테스트에서 개인 회원에 액세스 할 수 없습니다. 이것이 지원되어야하는지 여부와 개인 API를 전혀 테스트해야하는지에 대해 많은 논의가 있습니다 (언어와 무관). 퍼블릭 API 테스트는 각 코드 경로에 도달 할 수 있어야합니다. 나는 이것이 일반적으로 합리적이라고 생각합니다. Dart에서 private은 라이브러리 당 (여러 파일로 구성 될 수 있음) 공용 API를 상당히 광범위하게 만듭니다. IMHO는 단위 테스트에 비해 너무 광범위합니다.
Günter Zöchbauer 2016 년

3

프라이빗 변수는 컴포넌트 템플릿 내에서 사용할 수 있습니다. 가이드는 angular2 치트 시트를 참조하십시오 : https://angular.io/docs/ts/latest/cookbook/component-communication.html#!#parent-to-child-setter

typescript에서 공개 / 비공개 클래스 멤버에 대한 자세한 설명은 https://www.typescriptlang.org/docs/handbook/classes.html 에서 확인할 수 있습니다 .

기본적으로 모든 회원은 공개입니다. 클래스 멤버와 함께 구성 요소 클래스 외부에서 공개 멤버에 액세스 할 수 있습니다. 그러나 개인 멤버는 클래스 멤버 함수 내에서만 액세스 할 수 있습니다.


첫 번째 링크 ( angular.io/guide/component-interaction#!#parent-to-child-setter )를 보았고 템플릿에서 개인 변수를 사용하는 것이 괜찮다는 것을 알 수있는 곳은 없습니다. 반대로 getter와 setter를 사용하여 템플릿에서 개인 변수에 액세스합니다.
Sebastien Chartier

3

해결 방법은 ts 파일에서 개인 변수를 사용하고 getter를 사용하는 것입니다.

private _userName = "Test Name";
get userName() {
  return this._userName;
}

이것은 ts 파일과 html이 독립적으로 유지되기 때문에 좋은 접근 방법입니다. ts 파일에서 _userName 변수 이름을 변경하더라도 템플릿 파일을 변경할 필요는 없습니다.


일관성을 위해 예를 들어 일관성을 위해 _userName을 _clientName으로 변경하면 getter를 변경하여 clientName을 가져와야합니다. 따라서 승리가 없습니다
LeagueOfJava

개인 변수에 대한 사용자 밑줄은 나쁜 습관입니다.
Florian Leitgeb 8

1
@FlorianLeitgeb 왜 공식 Angular 문서가 그렇게 합니까? private _name = '';
ruffin

그런 다음이 코드 스 니펫이 제대로 검토되지 않았습니다. 그들은 스타일 가이드에 선언되어있는 스타일 규칙을 따라야 여기를 . 또한 자신의 페이지에 타이프 라이터 클래스 섹션에서 여기에 밑줄을 사용하지 않습니다.
Florian Leitgeb

1
@FlorianLeitgeb 그렇다면 ruffin이 게시 한 링크에 표시된 것처럼 setter 메소드의 차단에 제안 된 솔루션은 무엇입니까? 즉, 세터의 개인 지원 필드는 무엇입니까?
El Ronnoco

1

짧은 대답은 템플릿에서 기술적으로 TS 파일과 분리되어 있으므로 템플릿에서 개인 멤버에 액세스 할 수 없다는 것입니다.


0

tsconfig.app.json에서 컴파일러 옵션에 'fullTemplateTypeCheck'옵션을 제공하면 프로젝트 빌드시 프로젝트의 html 파일에서 유효하지 않은 모든 참조를 볼 수 있습니다.

"angularCompilerOptions": {
"enableIvy": true,
"fullTemplateTypeCheck": true

}

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