Angular 2는 HTML 5 웹 컴포넌트 기술을 포함합니다. 이 기술은 Angular 2 컴포넌트를 존재케한 기반기술입니다. 본 슬라이드는 이와 관련하여 2가지 흐름을 가지고 있습니다.
- 전반부는 웹 컴포넌트가 Angular 2 컴포넌트가 되기까지의 과정을 설명합니다.
- 후반부는 컴포넌트 트리 구조를 기반으로한 컴포넌트 상호작용에 대해 설명합니다.
필요하신 분에게 조금이라도 도움이 되었으면 좋겠습니다. 감사합니다.
CHANGE LOG
2016-06-27 : @input 데코레이터 설명교정
2016-06-26 : 쉐도우 돔 / 쉐도우 호스트관련 보다 정확한 문장으로 수정
2016-06-25 : 업로드
3. • 웹 컴포넌트는 W3C의 표준
• 웹 컴포넌트 이용을 위해 보완 라이브러리 필요
– webcomponent.js와 Polymer Library 이용
• 웹 컴포넌트의 구성요소
– HTML 탬플릿
– HTML 임포트
– 쉐도우 돔
– 커스텀 엘리먼트
웹 컴포넌트 (web components)
4. • 탬플릿 태그를 이용한 재사용 HTML 정의가능
– 탬플릿 태그내의 엘리먼트들은 랜더링 되지 않음
HTML 탬플릿
<template id=“nav-item-template">
<div class=’nav’>
<div class=“item">메인</div>
<div class=“item">서비스 소개</div>
<div class=“item">서비스 특징</div>
</div>
</template>
5. • 외부 HTML 탬플릿 문서를 가져오는 방법
– 문서를 가져오기 위해 CORS 허용설정 필요
HTML Import
<link rel="import" href="http://mydomain/my-elements.html">
HTML문서 임포트 예
<script>
var link = document.querySelector('link[rel="import"]');
var content = link.import;
var el = content.querySelector('.info');
document.body.appendChild(el.cloneNode(true));
</script>
외부에 정의한 HTML 탬플릿 사용
6. • 노출 되지 않는 돔이다.
• 쉐도우 경계를 가져 외부 접근이 불가함 (캡슐화)
쉐도우 돔 (Shadow Dom)
<button class="blue">버튼</button>
<script>
var button = document.querySelector('button');
var root = button.createShadowRoot();
root.innerHTML = '<style>' +
':host { color:blue; }' +
'</style>' +
'<content></content>';
</script>
버튼에 대한 쉐도우 돔 만들기
7. • 문서 돔은 쉐도우 돔을 랜더링 하지 않음
– 즉 쉐도우 호스트와 연결된 쉐도우 돔은 문서 DOM과
별개로 사전 랜더링됨
쉐도우 돔
문서 DOM
쉐도우 돔 (Shadow Dom)
8. • 쉐도우 돔은 독립 스타일을 가짐
쉐도우 돔 (Shadow Dom)
쉐도우 경계
독립 스타일
(스타일이 캡슐화됨)
9. • 사용자가 정의하며 확장 컴포넌트
커스텀 엘리먼트
var myProto = Object.create( HTMLButtonElement.prototype )
myProto.createdCallback = callback;
var helloButton = document.registerElement( 'hello-button', {
prototype: myProto,
extends: 'button'
} )
function callback (){
this.onclick = function ( event ){
alert( this.id + " " + this.value );
}} 콜백함수에 이벤트 등록
엘리먼트 확장
자바스크립트를 이용한 커스텀 엘리먼트 정의
17. • 블록 엘리먼트는 Angular 2 컴포넌트로 전환가능
– 컴포넌트로 영역과 블록 구조를 정의함
• Angular 2 컴포넌트는 중첩 가능하다.
– 즉, 컴포넌트로 블록 구조를 잡고 컴포넌트가 컴포넌트를
포함하는 방식으로 웹 어플리케이션을 만든다.
엘리먼트와 Angular 2 컴포넌트
19. 컴포넌트란?
• 서비스 컴포넌트 아키텍쳐에서의 컴포넌트 의미
– 명세에 따른 배포, 조립, 재사용 가능한 서비스 구성단위
• Angular 2 컴포넌트
– 웹 페이지에서 재사용 가능한 사용자 정의 엘리먼트
– 컴포넌트 = 탬플릿 + 로직
20. 외부모듈 호출
컴포넌트
클래스 정의
컴포넌트
메타데이터 설정
Angular 2 컴포넌트 구조
import { Component } from '@angular/core';
@Component({
selector: 'my-component',
template:'탬플릿이 위치하는 곳'
})
export class MyComponent {
//로직이 위치하는 곳
}
ts
21. 컴포넌트 용어정의
import { Component } from '@angular/core';
@Component({
selector: 'my-component',
template:`<div>hello {{component}}!</div>
<button (click)="hello()">hello</button>`
})
export class MyComponent {
constructor() {}
name:string;
sayHello() {}
}
컴포넌트
장식자
Angular
라이브러리
모듈
모듈 명
클래스 명
모듈 공개
(클래스모듈)
외부 모듈 호출
컴포넌트 지시자
탬플릿 속성
탬플릿 표현식
바인딩타입
생성자 메서드
컴포넌트 메서드
탬플릿 입력 변수
22. • 컴포넌트 장식자를 이용해 컴포넌트 설정 진행
컴포넌트 데코레이터
@Component({
selector: 'my-component',
template:''
})
재사용 가능한 UI 정의
23. • 컴포넌트 초기화
– 컴포넌트 초기화 훅 ngOnInit은 생성자 이후에 호출됨
컴포넌트 초기화
export class MyComponente implements OnInit {
constructor() { }
ngOnInit() { }
}
훅 메서드
(OnInit의 상속유무와 관계없이 호출됨)
생성자를 이용한 컴포넌트 초기화
24. • 컴포넌트에서 자식 컴포넌트 포함하기
중첩 컴포넌트 표현
import { Component } from '@angular/core';
@Component({
selector: 'my-app',
template:’<my-profile></my-profile>’
})
import { Component } from '@angular/core';
@Component({
selector: 'my-profile‘,
template:’나의 프로필입니다.’ })
export class MyComponent {
}
자식 컴포넌트
부모 컴포넌트
25. • 컴포넌트에서 서비스 주입받기
컴포넌트 서비스 주입
import { Injectable } from '@angular/core';
@Injectable()
export class HelloService {
getName() {
return "Hello";
}
}
import { HeroService } from './hero.service';
@Component({
selector: 'my-app',
template: ``,
providers: [HeroService]})
export class AppComponent implements OnInit {
constructor(private heroService: HeroService) { }
}
서비스
컴포넌트
26. • 부모 자식 컴포넌트간 데이터를 주고 받는 방법
• 상호작용을 위한 장식자
– @input : 부모로 부터 입력 받음
– @output : 자식이 부모 컴포넌트에게 데이터 전달
컴포넌트 상호작용
27. import { Component, EventEmitter, Input, Output } from
'@angular/core';
@Component({
selector: 'my-voter',
template: `
<h4>{{name}}</h4>
<button (click)="vote(true)" [disabled]="voted">Agree</button>
<button (click)="vote(false)" [disabled]="voted">Disagree</button>
`})
export class VoterComponent {
@Input() name: string;
@Output() onVoted = new EventEmitter<boolean>();
voted = false;
vote(agreed: boolean) {
this.onVoted.emit(agreed); // 부모 컴포넌트에 이벤트 전달
this.voted = true;
}}
컴포넌트 상호작용
자식 컴포넌트
28. 컴포넌트 상호작용
import { Component } from '@angular/core';
import { VoterComponent } from './voter.component';
@Component({
selector: 'vote-taker',
template: `
<h2>Should mankind colonize the Universe?</h2>
<h3>Agree: {{agreed}}, Disagree: {{disagreed}}</h3>
<my-voter *ngFor="let voter of voters"
[name]="voter" (onVoted)="onVoted($event)">
</my-voter>`,
directives: [VoterComponent]
})
export class VoteTakerComponent {
agreed = 0; disagreed = 0;
voters = ['Mr. IQ', 'Ms. Universe', 'Bombasto'];
onVoted(agreed: boolean) {
agreed ? this.agreed++ : this.disagreed++;
} }
부모 컴포넌트
자식 컴포넌트
이벤트 대기