Custom Element 만들기
주의 이 글은 다듬어 지지 않았습니다.
2018.1.4 확인 결과 사용되는 API 표준이 달라져있는 것을 확인 아래 글중에 정확하지 않은 정보가 포함되어 있다.
- https://developer.mozilla.org/en-US/docs/Web/Web_Components/Custom_Elements
- https://developer.mozilla.org/en-US/docs/Web/Web_Components/Custom_Elements/Custom_Elements_with_Classes
- https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_variables
- https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Creating_and_triggering_events
- https://www.html5rocks.com/en/tutorials/webcomponents/customelements/
- https://www.html5rocks.com/ko/tutorials/webcomponents/shadowdom/
- https://www.html5rocks.com/ko/tutorials/webcomponents/template/
- https://www.html5rocks.com/ko/tutorials/webcomponents/imports
- https://www.html5rocks.com/ko/tutorials/webcomponents/shadowdom-301/
- https://developer.mozilla.org/ko/docs/Web/Web_Components/Custom_Elements
- https://developers.google.com/web/updates/2016/06/css-containment?hl=ko
- https://gist.github.com/praveenpuglia/0832da687ed5a5d7a0907046c9ef1813
Polymer나 react js를 보면 Web components 기술을 기반으로 만들어 졌음을 알수 있다. Web component 기반 기술들은 html과 css, js로 나누어져서 작성되던 것들을 한곳을 뭉치기 쉽게 만든다. 물론 기존의 방법은 각각의 역활이 명확하기에 레이어를 분리하여 작성하도록 도와주고 각각의 패러다임은 각각의 역활을 구현하기 쉽도록 짜여져 있어서 그자체로 편한것은 맞지만, 큰 프로젝트일수록 하나의 로지컬한 조각이 반드시 세개로 나누어져야 하다보니, 조합하기가 쉽지 않은것이 사실이다. 그래서 Web component는 세가지로 나누어 진것은 똑같게 나누어 지게 하되 하나의 로지컬한 단위는 하나의 Web Component로 작성하도록 해서 이를 배포하기 쉽도록 한다.
목적
Web 표준만을 이용해서 html import로 쓸수 있는 custom element를 정의한다.
왜 polymer 나 react를 쓰지 않는가?
- 표준만 써도 별로 어렵지 않아서
- 그런 라이브러리가 어떻게 작성되는지 알려고,
- 연습삼아서
단점
- 내 개발환경(chrome 63 < ) 외에는 작동하는 것을 보장할수 없다.
- 바퀴를 다시 개발하는 꼴이다.
- 문제가 생겼을때, 검색하면 라이브러리 쓰지 그러냐는 답이 많다..
예제 코드
https://github.com/bluemir/zumo
<template class="zumo-dialog">
<style>
@import url("/static/css/custom-element.css");
:host {
position: absolute;
display: none;
background: var(--default-background);
color: var(--default-foreground);
border: 2px solid green;
padding: 1rem;
}
:host(.show) {
display: block;
top: 1rem;
left: 1rem;
}
</style>
<h2>
<content selector=".title"></content>
</h2>
<form>
<content selector=".body"></content>
<button class="ok" >OK</button>
<button class="cancel">Cancel</button>
</form>
</template>
<script>
(function(template){
class ZumoDialog extends HTMLElement {
constructor() {
super();
console.debug("create?")
}
// callback
// createdCallback
// attachedCallback
// detachedCallback
// attributeChangedCallback(attrName, oldVal, newVal)
createdCallback(){
var shadow = this.createShadowRoot();
var clone = document.importNode(template.content, true)
shadow.appendChild(clone);
this.addEventListener("submit", this.bind(this));
}
_submit() {
console.debug("[zumo-dialog:_submit]");
evt.preventDefault();
}
show() {
this.classList.add("show");
}
}
document.registerElement('zumo-dialog', ZumoDialog);
})(document.currentScript.ownerDocument.querySelector('template.zumo-dialog'))
</script>
현재 상황
표준안은 위의 예제와 다르다…
js module과의 상성이 그리 좋지는 않은 것 같다. js module 에서는 같은 html에 있는 template 를 손쉽게 접근할 방법이 없다.
Stylesheet 만 있는 import는 앞으로 쓸수 없을것 같다. style을 공용 모듈로 두고 불러와 쓰고 싶다면(color 같은거) 그냥 과거의 방식대로 style 안에서 import 하는 것이 낫다.
- https://github.com/TakayoshiKochi/deprecate-style-in-html-imports
- https://www.chromestatus.com/features/5144752345317376
- https://css-tricks.com/things-ive-learned-css-grid-layout/
결국 lib 하나 만듬. https://github.com/bluemir/web-components