Web Components - Part.I, @KIG 30th

64
Web Components part - I Chang W. Doh KIG 31st

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

Page 1: Web Components - Part.I, @KIG 30th

Web Componentspart - I

Chang W. Doh

KIG 31st

Page 3: Web Components - Part.I, @KIG 30th

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

Page 4: Web Components - Part.I, @KIG 30th

컴포넌트의 주요 개념

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

Page 5: Web Components - Part.I, @KIG 30th

Why?

Page 6: Web Components - Part.I, @KIG 30th

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

Page 7: Web Components - Part.I, @KIG 30th

YUI

Page 8: Web Components - Part.I, @KIG 30th

jQuery

Page 9: Web Components - Part.I, @KIG 30th

KENDO UI

Page 10: Web Components - Part.I, @KIG 30th

Angular

Page 11: Web Components - Part.I, @KIG 30th

Sencha

Page 12: Web Components - Part.I, @KIG 30th

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

Page 13: Web Components - Part.I, @KIG 30th
Page 14: Web Components - Part.I, @KIG 30th

Tag soup

Do you love this?

Page 15: Web Components - Part.I, @KIG 30th
Page 16: Web Components - Part.I, @KIG 30th

무엇이 필요한가?

Page 17: Web Components - Part.I, @KIG 30th

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

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

Page 18: Web Components - Part.I, @KIG 30th

조금 더 나아가서...

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

Page 19: Web Components - Part.I, @KIG 30th

웹 컴포넌트!

Page 20: Web Components - Part.I, @KIG 30th

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

Page 21: Web Components - Part.I, @KIG 30th

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

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

Page 22: Web Components - Part.I, @KIG 30th

Quick Overview

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

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

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

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

Page 23: Web Components - Part.I, @KIG 30th

Shadow DOM

Page 24: Web Components - Part.I, @KIG 30th

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

왜 Shadow DOM인가?

Page 25: Web Components - Part.I, @KIG 30th

Shadow DOM 101

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

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

Page 26: Web Components - Part.I, @KIG 30th

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

Page 27: Web Components - Part.I, @KIG 30th

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>

Page 28: Web Components - Part.I, @KIG 30th

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>. */}

Page 29: Web Components - Part.I, @KIG 30th

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>

Page 30: Web Components - Part.I, @KIG 30th

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 { ...}

Page 31: Web Components - Part.I, @KIG 30th

Shadow DOM 201

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

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

Page 32: Web Components - Part.I, @KIG 30th

Shadow DOM 201

● Cheat Sheet시나리오 applyAuthorStyles resetStyleInheritance

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

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

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

true true

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

Page 33: Web Components - Part.I, @KIG 30th

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>

Page 34: Web Components - Part.I, @KIG 30th

Custom elements

Page 35: Web Components - Part.I, @KIG 30th

Custom Elements

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

Page 36: Web Components - Part.I, @KIG 30th

Custom Elements

● 새로운 엘리먼트의 등록

● 기존 엘리먼트의 확장

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

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

Page 37: Web Components - Part.I, @KIG 30th

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);

Page 38: Web Components - Part.I, @KIG 30th

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});

Page 39: Web Components - Part.I, @KIG 30th

HTML Template

Page 40: Web Components - Part.I, @KIG 30th

HTML Template

● HTML Template 이전○ Text Templating○ Script Overloading

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

■ 보이지 않는 DOM

Page 41: Web Components - Part.I, @KIG 30th

HTML Template

● HTML Template 이전○ Text Templating○ Script Overloading

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

■ 보이지 않는 DOM

Page 42: Web Components - Part.I, @KIG 30th

HTML Template

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

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

Page 43: Web Components - Part.I, @KIG 30th

● 템플릿의 선언

HTML Template

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

Page 44: Web Components - Part.I, @KIG 30th

● 주요 특징○ 비활성화

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

○ 모든 위치에서 활용 가능

HTML Template

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

Page 45: Web Components - Part.I, @KIG 30th

● 템플릿의 사용

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>

Page 46: Web Components - Part.I, @KIG 30th

HTML Imports

Page 47: Web Components - Part.I, @KIG 30th

HTML Imports

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

Page 48: Web Components - Part.I, @KIG 30th

HTML Imports

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

Page 49: Web Components - Part.I, @KIG 30th

HTML Imports

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

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

Page 50: Web Components - Part.I, @KIG 30th

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)">

Page 51: Web Components - Part.I, @KIG 30th

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);

Page 52: Web Components - Part.I, @KIG 30th

HTML Imports

● link.import

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

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

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

Page 53: Web Components - Part.I, @KIG 30th

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>

Page 54: Web Components - Part.I, @KIG 30th

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>

Page 55: Web Components - Part.I, @KIG 30th

HTML Imports

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

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

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

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

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

Page 56: Web Components - Part.I, @KIG 30th

Tools

Page 57: Web Components - Part.I, @KIG 30th

Tools

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

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

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

Page 58: Web Components - Part.I, @KIG 30th

Conclusion

Page 59: Web Components - Part.I, @KIG 30th

Conclusion

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

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

Page 60: Web Components - Part.I, @KIG 30th

Resources

Page 63: Web Components - Part.I, @KIG 30th

Q&A

Page 64: Web Components - Part.I, @KIG 30th

Thank you!

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