angular2를 위한 컴포넌트 분석과 개발
TRANSCRIPT
Component Analysis and Development for Angular2Angular2 를 위한 컴포넌트 분석과 개발
2016 년 06 월 25 일 정진욱
웹 컴포넌트
• 웹 컴포넌트는 W3C 의 표준• 웹 컴포넌트 이용을 위해 보완 라이브러리 필요– webcomponent.js 와 Polymer Library 이용
• 웹 컴포넌트의 구성요소– HTML 탬플릿 – HTML 임포트– 쉐도우 돔– 커스텀 엘리먼트
웹 컴포넌트 (web components)
• 탬플릿 태그를 이용한 재사용 HTML 정의가능– 탬플릿 태그내의 엘리먼트들은 랜더링 되지 않음
HTML 탬플릿
<template id=“nav-item-template"><div class=’nav’>
<div class=“item"> 메인 </div><div class=“item"> 서비스 소개 </div><div class=“item"> 서비스 특징 </div>
</div></template>
• 외부 HTML 탬플릿 문서를 가져오는 방법– 문서를 가져오기 위해 CORS 허용설정 필요
HTML Import
<link rel="import" href="http://mydomain/my-ele-ments.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 탬플릿 사용
• 노출 되지 않는 돔이다 . • 쉐도우 경계를 가져 외부 접근이 불가함 ( 캡슐화 )
쉐도우 돔 (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>
버튼에 대한 쉐도우 돔 만들기
• 문서 돔은 쉐도우 돔을 랜더링 하지 않음– 즉 쉐도우 호스트와 연결된 쉐도우 돔은 문서 DOM 과
별개로 사전 랜더링됨 쉐도우 돔문서 DOM
쉐도우 돔 (Shadow Dom)
• 쉐도우 돔은 독립 스타일을 가짐
쉐도우 돔 (Shadow Dom)
쉐도우 경계
독립 스타일( 스타일이 캡슐화됨 )
• 사용자가 정의하며 확장 컴포넌트
커스텀 엘리먼트
var myProto = Object.create( HTMLButtonElement.prototype )myProto.createdCallback = callback;var helloButton = document.registerElement( 'hello-but-ton', { prototype: myProto, extends: 'button'} )
function callback (){ this.onclick = function ( event ){ alert( this.id + " " + this.value );}}
콜백함수에 이벤트 등록
엘리먼트 확장
자바스크립트를 이용한 커스텀 엘리먼트 정의
• 커스텀 엘리먼트 사용
커스텀 엘리먼트
<button is="hello-button" id="Hello" value="World"> Hello World! </button>
HTML 에서 커스텀 엘리먼트 입력
버튼 커스텀 엘리먼트의 실행결과
• Angular 2 는 웹 컴포넌트 기술을 사용한다 .– 탬플릿 태그를 이용한다 .– 쉐도우 돔을 통해 돔과 스타일을 캡슐화 한다 .– 컴포넌트는 커스텀 태그이다– 다른 탬플릿에 대한 임포트가 가능하다 .
웹 컴포넌트와 Angular 2 컴포넌트
엘리먼트에서 컴포넌트로 전환
• 블록구조는 블록 모양의 웹 페이지 구조를 말함• 블록구조는 HTML 5 의 시맨틱 태그로 표현함
블록구조 (block structure)
블록구조를 만드는 HTML5 블록 엘리먼트
• 블록 엘리먼트는 UI 를 가지며 컴포넌트로 전환가능
블록 엘리먼트를 컴포넌트로 전환
서비스 장점빠르다 쉽다 무료다
해피 주식회사 만든
section 컴포넌트의 UI
<nav> 태그 컴포넌트
컴포넌트로 대체한 시맨틱태그
• 컴포넌트는 자식 컴포넌트를 포함할 수 있음
중첩 컴포넌트 (nested compo-nent)
컴포넌트자식 컴포넌트
부모 컴포넌트
컴포넌트 트리
• 중첩 컴포넌트의 계층구조는 트리형임
컴포넌트 트리 (component tree)
• 블록 엘리먼트는 Angular 2 컴포넌트로 전환가능– 컴포넌트로 영역과 블록 구조를 정의함
• Angular 2 컴포넌트는 중첩 가능하다 .– 즉 , 컴포넌트로 블록 구조를 잡고 컴포넌트가 컴포넌트를
포함하는 방식으로 웹 어플리케이션을 만든다 .
엘리먼트와 Angular 2 컴포넌트
Angular 2 컴포넌트 개발
컴포넌트란 ?
• 서비스 컴포넌트 아키텍쳐에서의 컴포넌트 의미– 명세에 따른 배포 , 조립 , 재사용 가능한 서비스 구성단위
• Angular 2 컴포넌트 – 웹 페이지에서 재사용 가능한 사용자 정의 엘리먼트– 컴포넌트 = 탬플릿 + 로직
외부모듈 호출
컴포넌트클래스 정의
컴포넌트 메타데이터 설정
Angular 2 컴포넌트 구조import { Component } from '@angular/core';
@Component({ selector: 'my-component', template:' 탬플릿이 위치하는 곳 '})
export class MyComponent {
// 로직이 위치하는 곳} ts
컴포넌트 용어정의
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라이브러리모듈모듈 명
클래스 명모듈 공개( 클래스모듈 )
외부 모듈 호출
컴포넌트 지시자탬플릿 속성
탬플릿 표현식
바인딩타입생성자 메서드컴포넌트 메서드 탬플릿 입력 변수
• 컴포넌트 장식자를 이용해 컴포넌트 설정 진행
컴포넌트 데코레이터
@Component({ selector: 'my-component', template:''})
재사용 가능한 UI 정의
• 컴포넌트 초기화– 컴포넌트 초기화 훅 ngOnInit 은 생성자 이후에 호출됨
컴포넌트 초기화
export class MyComponente implements OnInit {
constructor() { }
ngOnInit() { }
}
훅 메서드(OnInit 의 상속유무와 관계없이 호출됨 )
생성자를 이용한 컴포넌트 초기화
• 컴포넌트에서 자식 컴포넌트 포함하기
중첩 컴포넌트 표현
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 {}
자식 컴포넌트
부모 컴포넌트
• 컴포넌트에서 서비스 주입받기
컴포넌트 서비스 주입
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) { } }
서비스
컴포넌트
• 부모 자식 컴포넌트간 데이터를 주고 받는 방법• 상호작용을 위한 장식자– @input : 부모로 부터 입력 받음– @output : 자식이 부모 컴포넌트에게 데이터 전달
컴포넌트 상호작용
import { Component, EventEmitter, Input, Output } from '@angular/core';@Component({ selector: 'my-voter', template: ` <h4>{{name}}</h4> <button (click)="vote(true)" [disabled]="voted">Agree</but-ton> <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; }}
컴포넌트 상호작용 자식 컴포넌트
컴포넌트 상호작용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++; } }
부모 컴포넌트
자식 컴포넌트이벤트 대기
• http://w3c.github.io/webcomponents/spec/custom/• https://www.w3.org/TR/shadow-dom/• http://w3c.github.io/webcomponents/spec/imports• https://
angular.io/docs/ts/latest/guide/component-styles.html• https://angular.io/docs/ts/latest/guide/lifecycle-hooks.html• https://
angular.io/docs/ts/latest/cookbook/component-communication.html
참고자료
고맙습니다고맙습니다