TIL_171109 Angular Component - Template, Date Binding, Built-in directive
앵귤러안에서는 DOM을 써도 되지만, 쓰는 순간 앵귤러의 의미를 잃어버린다.
되도록 쓰지 않도록 하나, Pure Javascript를 잊어버리지 않도록 유의*
용어정리
- Model : 애플리케이션에서 사용되는 데이터 형식 과 이를 컨트롤하는 로직 (비즈니스/유효성 검사)
- View : 사용자에게 model을 표시하는 것
- 구문 vs 표현식
- 구문: 시스템을 변경할 수 있고 ;으로 끝남
- 표현식: 값, 변수, 연산자의 조합으로 연산을 통해 하나의 값을 만듬
변화 감지
앵귤러는 Zone.js 라이브러리를 통해 아래의 변화를 감지
- DOM 이벤트
- Timer의 tick 이벤트
- Ajax / Promise
연결된 바인딩이 어떠한 상황에 변화하는가? (Zone.js가 체크하는 지점)
- 기본자료형은 pass by value기 때문에 메모리주소가 바뀌는 순간 변경을 감지
- 객체는 pass by reference기 때문에 메모리주소가 재할당되어야 변경을 감지
즉, 값이 바뀌지 않았다 하더라도 메모리주소가 변경되면 변화감지가 일어남
*filter와 같이 원본 배열은 그대로 두는 것은 변화감지가 일어나지 않음
Template Syntax
템플릿과 컴포넌트 클래스간의 데이터 공유를 위한 문법 (데이터 바인딩)
Data Binding
1. 인터폴레이션
- 표현식을 사용 (연산자 제외)
- 템플릿에는 하나의 값이 들어가고, 컴포넌트 클래스의 프로퍼티를 변경할 수 있는 연산자는 사용 금지
- 당연히 재할당을 지정하는 행위 역시 금지
- 프로퍼티 바인딩의 syntax sugar
2. 프로퍼티 바인딩*
- [property]=”expression”
- 표현식 평가 결과가 DOM 프로퍼티에 바인딩됨
- 즉, 컴파일 됐을때 html 마크업상으론 표현이 X, 오롯이 DOM에만
- 따라서 해당하는 태그의 DOM 프로퍼티가 있는지를 확인하고 바인딩을 사용해야 함
3. 어트리뷰트 바인딩
- [attr.attribute-name]=”expression”
- 보통 프로퍼티 바인딩으로 해결하지 못할때 사용 (td colspan 등)
[참고] DOM 프로퍼티 vs HTML 어트리뷰트*
HTML의 어트리뷰트는 DOM구조에서
(1) 대응하는 DOM의 프로퍼티와
(2) DOM의 ‘attribute’ 프로퍼티에 유사배열 형태로 저장
예를 들어 HTML input태그에 선언된 어트리뷰트는 DOM의 input element의 attribute 프로퍼티 에 유사배열형태로 저장 [id, type, value]
- 이 유사배열에 있는 value값은 초기값(선언한 값)을 가지고 있음
- 유저가 입력값을 바꾸면 바뀐 value값은 DOM property리스트의 value(대응하는 프로퍼티)가 저장
즉, DOM의 프로퍼티와 HTML의 어트리뷰트가 언제나 1:1로 매핑되는 것은 아님
- 서로에게 대응하는 어트리뷰트와 프로퍼티가 없을 수 있음 (class / classList)
- 같은 이름, 서로에게 대응하는 것이 있어도 다르게 동작할 수 있음 (value 예)
|
|
4. 클래스 바인딩
- [class.class-name]=”expression”
- 중복되는 경우 true면 병합되고 false면 원래 있던 것도 지움
- 클래스 바인딩은 클래스 어트리뷰트 보다 우선함
- 즉, 기존에 마크업된 클래스 어트리뷰트를 리셋, 클래스 바인딩의 내용을 적용
5. 스타일 바인딩
- [style.css프로퍼티명]=”expression”
- 인라인 스타일을 만들어줌
- font-size의 경우 단위까지 기술
- [style.font-size.em]=”isActive ? 1.2 : 1”
6. 이벤트 바인딩*
- (event)=”statement”
- 표현식이 아닌, 구문이 옴1234// 구문에 할당문이 옴(click)="isActive=!isActive"// $event는 addEventListener의 e객체(input)="onInput($event)"
7. 양방향 데이터 바인딩
- [(ngModel)]=”variable”
- 사용하기 위해서는 root module에 FormsModule을 추가해야함
- 양쪽의 단방향을 사용함으로써(프로퍼티, 이벤트바인딩) 양방향인 것처럼 사용 (syntax sugar)
- 양방향 데이터바인딩은 꼭 필요할 시만 사용 (성능이슈)
- 사용자 입력과 관련돤 DOM요소에 사용됨 (input, textarea, select.. 폼 컨트롤 요소)
|
|
Built-in directive
- 애플리케이션 전역에서 사용할 수 있는 공통 관심사를 분리하여 구현
- 공통된 관심사를 묶어 HTML 태그의 커스텀 어트리뷰트를 만든다는 개념
- 컴포넌트는 커스텀 태그를 만든다는 개념
디렉티브 3가지 유형
1. 컴포넌트 디렉티브(Component Directives)
- 컴포넌트의 템플릿을 표시하기 위한 디렉티브
- @Component내 seletor 프로퍼티에 임의의 디렉티브의 이름을 정의
2. 어트리뷰트 디렉티브(Attribute Directives)
- HTML 요소의 어트리뷰트와 같이 사용 (해당 요소의 모양, 동작을 제어)
- ngClass, ngStyle
3. 구조 디렉티브(Structural Directives)
- DOM 레이아웃을 변경
- 구조 디렉티브는 DOM 요소를 반복 생성(ngFor)
- 조건에 의한 추가 또는 제거(ngIf, ngSwitch)
어트리뷰트 디렉티브
1. ngClass
- ngClass는 문자열, 배열, 객체, 컴포넌트 메소드에 의한 클래스까지 지원
- 클래스 바인딩은 문자열에 의한 클래스만을 지원하지만,
- 즉, css세트를 쓰거나 조건에 의한 클래스 적용시 사용.
- 복수의 클래스 리스트를 조건(true/false or 함수사용)으로 컨트롤할때 사용
2. ngStyle
- 인라인 스타일을 만듬
구조 디렉티브
1. ngIf
… - 조건에 따라 요소를 표시할지 말지 (true/false) 결정할때 사용
- 스타일 바인딩(display:none)으로 하는것은 DOM요소가 남지만, ngIf는 아예 DOM까지 제거
- false일때의 구문 추가 가능 (else문)123<div *ngIf="mySkill==='HTML'; else elseBlock">HTML</div><!--else일때 실행할 elseBlock구문--><ng-template #elseBlock><div>CSS</div></ng-template>
2. ngFor
- 컴포넌트 클래스의 컬렉션을 반복(for문처럼)
- -> 호스트 요소 및 하위 요소를 DOM에 추가
- 컬렉션은 일반적으로 배열을 사용12345<!--기본 문법--><element *ngFor="let item of items">...</element><!--옵션 사항--><element *ngFor="let item of items; let i=index; let odd=odd; trackBy: trackById">...</element>
3. ngSwitch
- js의 switch문과 같은 기능
- 이전과는 달리 *를 case문에 사용