CodeSchool 의 Angular 2 강의 내용을 요약하였습니다.
Angular 1 과 2 의 차이점?
- Speed : Angular 2 가 많은 면에서 더 빠르다
- Components : Angular 1 의 Controller, Scope 대신에 사용
- Simpler Directives : Custom Directives 를 생성하기 쉬워짐
- Intuitive Data Binding : HTML 요소나 버튼에 이벤트 리스너를 설치할 떄 더 직관적인 신택스 제공
- Services : 이제는 클래스로 선언
Angular 2 에서는 어떤 언어를 사용하나?
- Javascript 로 코딩이 가능하지만 모든 브라우저에서 최신 버전의 자바스크립트를 지원하지는 않기 때문에. Babel & TypeScript 를 이용하여 Transpile (모든 브라우저에서 호환 가능한 Javascript 로 변환)한 후 사용한다.
TypeScript
- 마이크로소프트에서 확장한 자바스크립트
- ES2015 피쳐 : 강력한 타입 체크와, 객체 지향 기능들을 지원
- 확장자명 .ts
- 타입스크립트 홈피
Transpiling 위치
- 브라우저에서 TypeScript 를 Javascript 로 변환하는 방법 과 브라우저에 보내기 전에 TypeScript 를 빌드하고 Javascript 로 변환하고 난 후 브라우저로 보내는 방법 이렇게 두가지가 존재한다.
- 후자가 당연히 더 빠르고, 실제 서비스 할 때 권고하는 방법이다.
Backtic
- Angular 2 에서는 Double Quote 대신에 Backtic 이라는 ` ` 를 사용하여 템플릿을 설정할 수 있다.
Angular 2 라이브러리 로딩
- 사이트를 참고하여 Angular 2 에 필요한 라이브러리 로딩에 대해서 알아본다.
Part 1 Conclusion
- Angular 는 다이나믹 웹 앱을 위한 프레임워크
- TypeScript 를 이용하여 Angular 를 코딩할 수 있다. TypeScript 는 자바스크립트로 변환해주는 언어
- Decorator 는 플레인 TypeScript 클래스들을 Components 로 변환해준다
- Components are the building blocks of our application.
Directives
- HTML 요소에 동적인 기능이나 동작을 추가할 수 있게 하는 Angular 구성요소
- 3가지 종류 : Component / Structural / Attribute
Structural Directives
- *ngFor : Loop the array
-
*ngIf : conditional statement
<li *ngFor="let carPart of carParts"> <p *ngIf="carPart.inStock > 0"> in Stock</p> <p *ngIf="carPart.inStock === 0">Out of Stock</p>
Pipes & Methods
- Pipes : 템플릿의 데이터를 우리가 원하는 방식으로 가공해서 보여줄 수 있는 기능
- ex) currency, lowercase, etc
- Methods : 클래스 안에 생성이 가능하고,
function
키워드를 넣을 필요 없음 (ES2015 문법)
ES 2015 Fat Arrow
-
ES2015 에 등장하는 새로운 함수 정의법
=>
을 살펴보자.// Old Javascript totalCarParts() { return this.carParts.reduce(function(prev, current) {return prev + current.inStock; }, 0); } // ES2015 Fat Arrow Usage totalCarParts() { return this.carParts.reduce((prev, current) => prev + current.inStock, 0); }
파일 구조화 하기
-
main.ts
파일을 다음 3개의 파일로 분할main.ts
: 앱 초기화 및 첫번째 컴포넌트 로딩app.component.ts
: 페이지 헤더car-parts.component.ts
: car parts 리스트
분할된 파일의 클래스를 어떻게 접근하는가?
- class 앞에
export
예약어 추가 :export class
- main.ts 파일에서
import
로 파일의 클래스 접근 :import { AppComponent } from './app.component';
- @NgModule 데코레이션에 해당 컴포넌트 추가
@NgModule({
declarations: [
AppComponent,
CarPartsComponent // 추가된 컴포넌트
],
})
CSS 의 컴포넌트 Scoping
-
특정 컴포넌트에 해당하는 CSS 스타일링이 가능하다. (아래 챕터에서 나온 구조화를 진행하면 별도의 지정어 없이도 Angular 에서 자동으로 컴포넌트에만 국한되는 스코핑을 한다)
<p _ngcontent-dcy-2 class="description"> <p _ngcontent-dcy-2 class="price"> .description[_ngcontent-dcy-2] { color: #444; font-size: small; } .price[_ngcontent-dcy-2] { font-weight: bold; } <!-- 위 스타일링은 해당 클래스 중 _ngcontent-dcy-2 를 갖고 있는 태그에만 적용된다 -->
Javascript & HTML & CSS 의 구조화
-
한개의 Component 안에 너저분하게 html, css 가 모두 들어가는 것 보단 아래와 같이 scalable 하게 구조화가 가능하다.
import { Component } from '@angular/core'; @Component({ selector: "car-parts", templateUrl: "app/car-parts.component.html", styleUrls: ['app/car-parts.component.css'] })
Mocks & Models
const
: 해당 변수의 내용이 재정의 되지 않도록 설정 (ES2015)ngOnInit()
: 해당 컴포넌트가 생성되고 나면 바로 실행된다. 따라서, 프로퍼티 값을 초기화하기에 가장 안성맞춤인 장소. 컴포넌트 내의 다른 장소에서 프로퍼티 값 초기화도 가능하지만, 테스트하기에 어려움이 있다. 따라서 ngOnInit 에서 초기화 하도록 한다.
현재까지의 Component 구조
- index.html 로딩 :
<my-app>
을 포함하고 있고, main.ts 를 호출 - main.ts 로딩 : 첫번째 컴포넌트를 호출하고, 전체 앱을 부트스트래핑
- app.component.ts : 첫번째 컴포넌트이자, 헤더를 로딩한다. 그리고 이하 컴포넌트들을 로딩한다.
car-parts.component.ts
: javascript 로직car-part.ts
: 데이터 모델mocks.ts
: 가짜 데이터car-parts.component.html
: html 템플릿car-parts.component.css
: css 스타일
Best Practices about Mocks and Models
- TypeScript 에서는 클래스를 이용하여 데이터를 모델링한다.
- TypeScript 는 클래스의 속성 타입을 지정하여, 우리가 좋은 코드를 작성하고 있는지 컴파일러에게 확인시킨다.
- 가짜 데이터 작성은 별도의 파일로 분리해서 관리하는 것이 좋다.
Property and Class binding
- one way binding : 컴포넌트 프로퍼티 값으로 DOM 속성을 변경할 수 있지만, 그 반대는 되지 않는다
Event Binding
- 화면에서 발생하는 이벤트를 괄호() 로 묶고, 해당 이벤에 따라 수행되는 메서드 명을 지정한다 :
(click)="upQuantity(carPart)"
$event
객체는 화면에서 발생한 이벤트의 값을 저장한다 :<input type="text" (keydown)="showKey($event)">
Two way Binding
-
투 웨이 바인딩을 하기 위해서는 2가지 방법이 있다.
<input [value]="carPart.quantity" (input)="carPart.quantity = $event.target.value">
- FormsModule 임포트 후 추가
-
Model 의 Banana in a box : 네모 괄호 안에 둥근 괄호를 넣으면 Model 이 양방향으로 바인딩 된다.
[( )]
[(ngModel)] = "cash"
Services
- 서비스 : 앱의 코드를 공유하거나 구성하는데 사용되고, 주로 데이터 접근 메서드를 생성할 때 사용한다.
- Dependency Injection 은 서비스를 생성하고 클래스에 보낼 때 사용된다.
- DI 에 Provider 를 제공함으로써 어떤 클래스가 서비스 생성이 필요한지를 알 수 있다.
class constructor
에 서비스를 지정함으로써 DI 에게 클래스 생성 여부를 요청할 수 있다.- The injector knows how to inject our dependencies
- inject : Create (if needed) and send
- dependencies : Classes we depend on
-
DI 에 Providers 를 등록하는 법 (RacingDataService)
- 주입할 수 있는 데코레이터를 Service 에 추가
- 인젝터에 서비스를 프로바이더로 명명하여 알게한다
- 디펜던시를 ts 파일에 주입한다.
주입할 수 있는 데코레이터를 Service 에 추가
import { Injectable } from '@angular/core';
@Injectable()
export class ~~ {
}
인젝터에 서비스를 프로바이더로 명명하여 알게한다
import { RacingDataService } from `./racing-data.service`;
@NgModule({
providers: [ RacingDataService]
})
디펜던시를 ts 파일에 주입한다
import { RacingDataService } from `./racing-data.service`;
@Component({ ... })
export class CapPartsComponent {
carParts: CarPart[];
// 서비스 생성
constructor(private racingDataService: RacingDataService) { }
// 위 문장은 다음과 같다.
function CarPartsComponent(racingDataService) {
this.racingDataService = racingDataService;
}
}
HTTP
-
HTTP 라이브러리 등록 절차
- JSON 파일 생성
- HTTP 라이브러리 포함
- Injector 에 http 프로바이더 전달
- http 디펜던시 주입 후, http get 요청
- 요청에 반환되는 데이터 대기
-
main.ts 에 아래와 같이 포함
import { HttpModule } from "@angular/http"; @NgModule({ imports: [HttpModule], providers: [], // http 모듈을 보면 이미 provider 리스트에 등록이 되어 있으므로, 프로바이더에 따로 등록할 필요는 없다. })
-
service.ts 에 아래와 같이 포함
import { Http } from "@angular/http"; import "rxjs/add/operator/map"; @Injectable() export class RacingDataService { constructor(private http: Http) { } // HTTP 디펜던시 주입 getCarParts() { return this.http.get('app/car-parts.json').map(response => <CapPart[]>response.json().data); } }
- 위 코드에 관한 설명은 다음 이미지 참조
- http 는 Observable 이라는 형태의 데이터로 반환해준다.
- 테스트나 오프라인시에는 RacingDataServiceMock 같은 서비스 명을 활용하여 테스트 하도록 한다.