21. 웹 컴포넌트를 지탱하는 4가지 기둥
1. Shadow DOM
2. Custom Elements
3. HTML Templates
4. HTML Imports
22. Quick Overview
● Shadow DOM
○ 컴포넌트를 구성하는 DOM, CSS, JS 캡슐화 및 외부
로부터의 간섭을 제어할 수 있도록 스코프 분리
● HTML Template
○ 정의된 마크업을 비활성화된 상태로 로딩 및 런타임
사용
● Custom Element
○ 웹 문서에서 사용할 엘리먼트의 동적인 등록 및 확장
● HTML Imports
○ 외부로부터 웹 문서 내에 문서의 일부/전체를 포함하
기 위한 방법 제공
24. ● 하나의 페이지 = 하나의 문서
○ 다만 브라우저가 하나의 문서로 통합하여 제어
○ 개발 시 다른 요소들과의 구조적인 이슈들이 발생
왜 Shadow DOM인가?
25. Shadow DOM 101
● 특정한 DOM을 서브 DOM 트리로 렌더링
○ 즉, 컨텐츠를 표현과 분리
● Shadow Host vs. Shadow Root
○ root = hostNode.createShadowRoot()
○ <content select=’query’></content>
○ DOM Visualizer
28. 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>. */
}
29. 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>
31. Shadow DOM 201
● .resetStyleInheritance
○ true - 상속가능한 속성들을 initial으로 재설정합니다.
○ false - 상속 가능한 CSS 속성들이 상속을 유지합니
다.
● .applyAuthorStyles
○ true - 저작자의 문서 내에 정의된 속성을 적용합니다.
○ false - 디폴트. 스타일은 섀도 트리에 적용되지 않습
니다.
32. Shadow DOM 201
● Cheat Sheet
시나리오 applyAuthorStyles resetStyleInheritance
자체적인 테마를 가지고 있
으나 기본 상속 속성은 유지
false false
자체적인 스타일 테마 유지 false true
페이지로부터 스타일 테마
만
true true
최재한 페이지에 가깝게 true false
35. Custom Elements
● 무엇을 할 수 있을까?
○ 새로운 엘리먼트의 등록
○ 기존 엘리먼트를 상속한 새로운 엘리먼트 확장
○ Tag에 대한 사용자 기능 지정/추가
○ 기존 엘리먼트의 메소드/이벤트 확장
36. Custom Elements
● 새로운 엘리먼트의 등록
● 기존 엘리먼트의 확장
var XFoo = document.registerElement('x-foo');
document.body.appendChild(new XFoo());
var MegaButton = document.registerElement('mega-button', {
prototype: Object.create(HTMLButtonElement.prototype)
});
37. 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);
38. 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});
40. HTML Template
● HTML Template 이전
○ Text Templating
○ Script Overloading
■ <script type=”text/template></script>
○ Offline DOM
■ 보이지 않는 DOM
41. HTML Template
● HTML Template 이전
○ Text Templating
○ Script Overloading
■ <script type=”text/template></script>
○ Offline DOM
■ 보이지 않는 DOM
42. HTML Template
● 지원 여부 검사
function supportsTemplate() {
return 'content' in document.createElement('template');
}
if (supportsTemplate()) {
// Good to go!
} else {
// Use old templating techniques or libraries.
}
44. ● 주요 특징
○ 비활성화
■ 렌더링되지 않고
■ 스크립트는 실행되지 않으며
■ 리소스(이미지, 오디오 등)는 로딩되지 않고
■ 문서 내에서 정상적인 방법으로 액세스되지 않음
○ 모든 위치에서 활용 가능
HTML Template
<table>
<tr>
<template id="cells-to-repeat">
<td>some content</td>
</template>
</tr>
</table>
45. ● 템플릿의 사용
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>
48. HTML Imports
● 무엇이던지 불러올 수 있는 마법의 도구!
<head>
<link rel="import" href="/path/to/imports/stuff.html">
</head>
49. HTML Imports
● 지원 여부
function supportsImports() {
return 'import' in document.createElement('link');
}
if (supportsImports()) {
// 지원하므로 그대로 진행합니다.
} else {
// 파일을 로딩하기 위한 다른 라이브러리나 require 시스템들을 사용하세요.
}
50. 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)">
51. HTML Imports
● Scripting HTML Imports
var link = document.createElement('link');
link.rel = 'import';
link.href = 'file.html'
link.onload = function(e) {...};
link.onerror = function(e) {...};
document.head.appendChild(link);
52. HTML Imports
● link.import
● 단, 아래의 경우에는 null
○ 브라우저가 HTML Imports를 지원하지 않을 경우
○ <link>가 rel="import"를 가지지 않을 경우 <link>가
DOM에 추가되지 않은 경우
○ <link>가 DOM으로부터 제거된 경우
○ 리소스가 'CORS가 가능한 상태'가 아닐 경우.
var content = document.querySelector('link[rel="import"]').import;
53. 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>
54. 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>
55. HTML Imports
● 웹 컴포넌트의 배포에 적합
○ HTML Template
■ 위젯의 마크업을 구축
○ Shadow DOM
■ 문서와 분리된 캡슐화된 HTML, JS, CSS 정의
○ Custom Element
■ 컴포넌트를 엘리먼트로 등록/확장
○ HTML Import 규격
■ HTML, CSS, 자바스크립트를 묶어서 로딩하도록
Importer 구성
57. Tools
● Yeoman
○ Yo - 작업 흐름 관리 도구
○ Grunt - 빌드/테스팅 등의 태스크 러너
○ Bower - 컴포넌트 배포 및 의존성 관리
● Polymer
○ 웹 컴포넌트를 위한 Polyfill 라이브러리 프로젝트
● Bricks
○ x-tag 기반의 웹 컴포넌트 Polyfill 라이브러리
59. Conclusion
생산성, 배포 및 관리 측면에서 피할 수 없는 흐
름
● “자주 사용되는 유용한 것들 혹은 구조 상 분리가 필요한
것들을 개발의 다른 요소들과 충돌하지 않는 형태로 재
활용이 가능하도록 만들어 주는 일관적인 방법”
미래를 예상해보자면...
● 프레임워크와 도구의 변화가 예상
● 웹 개발 도구 시장에서 컴포넌트의 위치 변화
61. HTML5Rocks: Web Component Tutorials
● Shadow DOM 101
● Shadow DOM 201: CSS & Styling
● Shadow DOM 301: Advanced Concepts & DOM API
● HTML Imports: #include for Web
● Custom Element: Defining new elements in HTML
● HTML’s new Template Tag: Standarizing client-side
templating
Further readings...
62. Resources
● Introduction to Web Components
● webcomponents.github.io
● Polymer Project
● Mozilla Brick
● Yeoman.io