Web Components - Part.I, @KIG 30th

Post on 15-Jan-2015

983 views 6 download

description

Quick overview of Web Component, HTML5Rocks/KO 1. Shadow DOM 2. Custom Elements 3. HTML Templates 4. HTML Imports

Transcript of Web Components - Part.I, @KIG 30th

Web Componentspart - I

Chang W. Doh

KIG 31st

“태양 아래 새로운 것은 없다.”

컴포넌트의 주요 개념

1. 재사용성2. 조합성3. 모듈화

Why?

웹에서 컴포넌트를 구현하는 다양한 방법

YUI

jQuery

KENDO UI

Angular

Sencha

“우리 구현을 조금 바꾸어야겠는데?”

Tag soup

Do you love this?

무엇이 필요한가?

“자주 사용되는 유용한 것들 혹은 구조 상 분리가 필요한 것들을 개발의 다른 요소들과 충돌하지 않는 형태로 재활용이

가능하도록 만들어 주는 일관적인 방법”

조금 더 나아가서...

● 특히, UI 요소들이 많은 프론트엔드 개발에서는○ “리소스 관점에서 분리되어 있는 HTML, CSS, 자바스크립트를 하나로 묶어 재활용할 수 있으면 좋겠다.”

웹 컴포넌트!

프론트엔드 웹을 위한 컴포넌트 시스템

웹 컴포넌트를 지탱하는 4가지 기둥

1. Shadow DOM2. Custom Elements3. HTML Templates4. HTML Imports

Quick Overview

● Shadow DOM ○ 컴포넌트를 구성하는 DOM, CSS, JS 캡슐화 및 외부로부터의 간섭을 제어할 수 있도록 스코프 분리

● HTML Template○ 정의된 마크업을 비활성화된 상태로 로딩 및 런타임 사용

● Custom Element○ 웹 문서에서 사용할 엘리먼트의 동적인 등록 및 확장

● HTML Imports○ 외부로부터 웹 문서 내에 문서의 일부/전체를 포함하기 위한 방법 제공

Shadow DOM

● 하나의 페이지 = 하나의 문서○ 다만 브라우저가 하나의 문서로 통합하여 제어○ 개발 시 다른 요소들과의 구조적인 이슈들이 발생

왜 Shadow DOM인가?

Shadow DOM 101

● 특정한 DOM을 서브 DOM 트리로 렌더링○ 즉, 컨텐츠를 표현과 분리

● Shadow Host vs. Shadow Root○ root = hostNode.createShadowRoot()○ <content select=’query’></content>○ DOM Visualizer

Shadow DOM 201

● Shadow DOM의 스타일링○ 섀도 경계(Shadow Boundary)

<div><h3>Light DOM</h3></div><script>var root = document.querySelector('div').createShadowRoot();root.innerHTML = '<style>h3{ color: red; }</style>' + '<h3>Shadow DOM</h3>';</script>

Shadow DOM

Shadow DOM 201

● host: 셀렉터○ hostNode에 대한 셀렉터

<style>:host { opacity: 0.4; transition: opacity 420ms ease-in-out;}:host:hover { opacity: 1;}:host:active { position: relative; top: 3px; left: 3px;}</style>

Shadow DOM 201

● 함수형 :host()

:host(x-foo:host) { /* Applies if the host is a <x-foo> element.*/}

:host(x-bar:host) { /* Applies if the host is a <x-bar> element. */}

:host(div) { { /* Applies if the host element or an ancestor is a <div>. */}

Shadow DOM 201

● hat - ^<style> #host ^ span { color: red; }</style>

<div id="host"> <span>Light DOM</span></div>

<script> var host = document.querySelector('div'); var root = host.createShadowRoot(); root.innerHTML = "<span>Shadow DOM</span>" + "<content></content>";</script>

Shadow DOM 201

● hat - cont’d

● cat - ^^

// No fun.document.querySelector('x-tabs').shadowRoot .querySelector('x-panel').shadowRoot .querySelector('#foo');

// Fun.document.querySelector('x-tabs ^ x-panel ^ #foo');

x-tabs ^^ x-panel { ...}

Shadow DOM 201

● .resetStyleInheritance○ true - 상속가능한 속성들을 initial으로 재설정합니다.○ false - 상속 가능한 CSS 속성들이 상속을 유지합니다.

● .applyAuthorStyles○ true - 저작자의 문서 내에 정의된 속성을 적용합니다.○ false - 디폴트. 스타일은 섀도 트리에 적용되지 않습니다.

Shadow DOM 201

● Cheat Sheet시나리오 applyAuthorStyles resetStyleInheritance

자체적인 테마를 가지고 있으나 기본 상속 속성은 유지 false false

자체적인 스타일 테마 유지 false true

페이지로부터 스타일 테마만

true true

최재한 페이지에 가깝게 true false

Shadow DOM 201

● ::content - 호스트 노드의 엘리먼트들을 한정<script>var div = document.querySelector('div');var root = div.createShadowRoot();root.innerHTML = '\ <style>\ h3 { color: red; }\ content[select="h3"]::content > h3 {\ color: green;\ }\ ::content section p {\ text-decoration: underline;\ }\ </style>\ <h3>Shadow DOM</h3>\ <content select="h3"></content>\ <content select="section"></content>';</script>

Custom elements

Custom Elements

● 무엇을 할 수 있을까?○ 새로운 엘리먼트의 등록○ 기존 엘리먼트를 상속한 새로운 엘리먼트 확장○ Tag에 대한 사용자 기능 지정/추가○ 기존 엘리먼트의 메소드/이벤트 확장

Custom Elements

● 새로운 엘리먼트의 등록

● 기존 엘리먼트의 확장

var XFoo = document.registerElement('x-foo');document.body.appendChild(new XFoo());

var MegaButton = document.registerElement('mega-button', { prototype: Object.create(HTMLButtonElement.prototype)});

Custom Elements

● 프로퍼티 및 메소드 추가var XFooProto = Object.create(HTMLElement.prototype);

// 1. x-foo에 foo() 메서드 주기.XFooProto.foo = function() { alert('foo() called');};// 2. read-only 속성의 "bar" 프로퍼티 정의.Object.defineProperty(XFooProto, "bar", {value: 5});// 3. x-foo의 정의를 등록하기.var XFoo = document.registerElement('x-foo', {prototype: XFooProto});// 4. x-foo 인스턴스화 .var xfoo = document.createElement('x-foo');// 5. xfoo 인스턴스를 페이지에 추가.document.body.appendChild(xfoo);

Custom Elements

● 몇가지 콜백Callback Description

createdCallback 엘리먼트의 인스턴스가 새로 생성되었을 때

attachedCallback 엘리먼트의 인스턴스가 document에 삽입되었을 때

detachedCallback 엘리먼트의 인스턴스가 document에서 삭제되었을 때

attributeChangedCallback 속성의 추가/삭제/갱신이 일어났을 때

var proto = Object.create(HTMLElement.prototype);

proto.createdCallback = function() {...};proto.attachedCallback = function() {...};

var XFoo = document.registerElement('x-foo', {prototype: proto});

HTML Template

HTML Template

● HTML Template 이전○ Text Templating○ Script Overloading

■ <script type=”text/template></script>○ Offline DOM

■ 보이지 않는 DOM

HTML Template

● HTML Template 이전○ Text Templating○ Script Overloading

■ <script type=”text/template></script>○ Offline DOM

■ 보이지 않는 DOM

HTML Template

● 지원 여부 검사function supportsTemplate() { return 'content' in document.createElement('template');}

if (supportsTemplate()) { // Good to go!} else { // Use old templating techniques or libraries.}

● 템플릿의 선언

HTML Template

<template id="mytemplate"> <img src="" alt="great image"> <div class="comment"></div></template>

● 주요 특징○ 비활성화

■ 렌더링되지 않고■ 스크립트는 실행되지 않으며■ 리소스(이미지, 오디오 등)는 로딩되지 않고■ 문서 내에서 정상적인 방법으로 액세스되지 않음

○ 모든 위치에서 활용 가능

HTML Template

<table><tr> <template id="cells-to-repeat"> <td>some content</td> </template></tr></table>

● 템플릿의 사용

HTML Template

<button onclick="useIt()">Use me</button><div id="container"></div><script> function useIt() { var content = document.querySelector('template').content; // 템플릿 DOM에서 뭔가를 갱신합니다 . var span = content.querySelector('span'); span.textContent = parseInt(span.textContent) + 1; document.querySelector('#container').appendChild( document.importNode(content, true)); }</script>

<template> <div>Template used: <span>0</span></div> <script>alert('Thanks!')</script></template>

HTML Imports

HTML Imports

● Imports 이전○ <iframe>○ Ajax○ Script hack!

HTML Imports

● 무엇이던지 불러올 수 있는 마법의 도구!<head> <link rel="import" href="/path/to/imports/stuff.html"></head>

HTML Imports

● 지원 여부function supportsImports() { return 'import' in document.createElement('link');}

if (supportsImports()) { // 지원하므로 그대로 진행합니다 .} else { // 파일을 로딩하기 위한 다른 라이브러리나 require 시스템들을 사용하세요 .}

HTML Imports

● Import 이벤트 핸들링<script async> function handleLoad(e) { console.log('Loaded import: ' + e.target.href); } function handleError(e) { console.log('Error loading import: ' + e.target.href); }</script>

<link rel="import" href="file.html" onload="handleLoad(event)" onerror="handleError(event)">

HTML Imports

● Scripting HTML Importsvar link = document.createElement('link');link.rel = 'import';link.href = 'file.html'link.onload = function(e) {...};link.onerror = function(e) {...};document.head.appendChild(link);

HTML Imports

● link.import

● 단, 아래의 경우에는 null○ 브라우저가 HTML Imports를 지원하지 않을 경우○ <link>가 rel="import"를 가지지 않을 경우 <link>가

DOM에 추가되지 않은 경우○ <link>가 DOM으로부터 제거된 경우○ 리소스가 'CORS가 가능한 상태'가 아닐 경우.

var content = document.querySelector('link[rel="import"]').import;

HTML Imports

● 삽입자<head> <link rel="import" href="warnings.html"></head><body> ... <script> var link = document.querySelector('link[rel="import"]'); var content = link.import;

// Grab DOM from warning.html's document. var el = content.querySelector('.warning');

document.body.appendChild(el.cloneNode(true)); </script></body>

HTML Imports

● Scripting in importer<link rel="stylesheet" href="http://www.example.com/styles.css"><link rel="stylesheet" href="http://www.example.com/styles2.css">...

<script> // importDoc은 import의 문서를 참조합니다 . var importDoc = document.currentScript.ownerDocument;

// mainDoc 메인 도큐먼트(우리가 import한 페이지)를 참조합니다 . var mainDoc = document;

// 첫번째 스타일시트를 이 import로부터 붙잡아 복제하고, // import된 문서에 추가합니다 . var styles = importDoc.querySelector('link[rel="stylesheet"]'); mainDoc.head.appendChild(styles.cloneNode(true));</script>

HTML Imports

● 웹 컴포넌트의 배포에 적합○ HTML Template

■ 위젯의 마크업을 구축○ Shadow DOM

■ 문서와 분리된 캡슐화된 HTML, JS, CSS 정의○ Custom Element

■ 컴포넌트를 엘리먼트로 등록/확장○ HTML Import 규격

■ HTML, CSS, 자바스크립트를 묶어서 로딩하도록 Importer 구성

Tools

Tools

● Yeoman○ Yo - 작업 흐름 관리 도구○ Grunt - 빌드/테스팅 등의 태스크 러너○ Bower - 컴포넌트 배포 및 의존성 관리

● Polymer○ 웹 컴포넌트를 위한 Polyfill 라이브러리 프로젝트

● Bricks○ x-tag 기반의 웹 컴포넌트 Polyfill 라이브러리

Conclusion

Conclusion

생산성, 배포 및 관리 측면에서 피할 수 없는 흐름● “자주 사용되는 유용한 것들 혹은 구조 상 분리가 필요한 것들을 개발의 다른 요소들과 충돌하지 않는 형태로 재활용이 가능하도록 만들어 주는 일관적인 방법”

미래를 예상해보자면...● 프레임워크와 도구의 변화가 예상● 웹 개발 도구 시장에서 컴포넌트의 위치 변화

Resources

Q&A

Thank you!

프리젠테이션 자료에서 사용된 이미지와 소스 등은 HTML5Rocks.com의 튜토리얼에서 인용되었습니다.