Custom Element

À¥ ÄÄÆ÷³ÍÆ®¸¦ ±¸¼ºÇÏ´Â Ä¿½ºÅÒ ¿¤¸®¸ÕÆ®¿¡ ´ëÇؼ­ ¾Ë¾Æ º¸ÀÚ.
ES6ÀÇ class¸¦ »ç¿ëÇؼ­ ¸¸µé¾î º»´Ù.

Ä¿½ºÅÒ ¿¤¸®¸ÕÆ®¸¦ »ç¿ëÇÏ°Ô µÇ¸é HTML, csss, javascript¸¦ ÇϳªÀÇ °´Ã¼·Î Ãë±ÞÇÒ¼ö ÀÖ´Ù.
»ý¼º, ¼Ò¸ê, ¾÷µ¥ÀÌÆ®½Ã º°µµÀÇ observer¸¦ ±¸Çö ÇÒ ÇÊ¿ä°¡ ¾ø´Ù.
class¿¡¼­ Áö¿øÇØÁÖ´Â ¸Þ¼­µåÀ» ÀÌ¿ëÇØ ±¸ÇöÇÏ¸é µÈ´Ù.

±¸Çö ´Ü°è´Â Å©°Ô 3´Ü°èÀÌ´Ù.
  1. Ŭ·¡½º ±¸Çö
  2. customElements.defineÀ¸·Î Ä¿½ºÅÒ ¿¤¸®¸ÕÆ® Á¤ÀÇ
  3. Ä¿½ºÅÒ ¿¤¸®¸ÕÆ® »ç¿ë

1. Ŭ·¡½º ±¸Çö

  1. HTMLElement Ŭ·¡½º¸¦ »ó¼ÓÇÑ´Ù.
    »ý¼ºÀÚ¿¡¼­ ºÎ¸ðÀÇ »ý¼ºÀÚ¸¦ È£ÃâÇØ¾ß ÇÑ´Ù.
  2. observedAttributes ¸Þ¼­µå¿¡¼­  ¸ð´ÏÅÍÇÒ ¼Ó¼ºÀ» Á¤ÀÇÇÑ´Ù.
    ¼Ó¼ºÀÌ ¹Ù²î¸é attributeChangedCallback ¸Þ¼­µå°¡ È£ÃâµÈ´Ù.
  3. attributeChangedCallback ³»¿ë, UI¸¦ ¾÷µ¥ÀÌÆ® ÇÑ´Ù.
  4. ¼Ó¼ºÀÇ set, get, ¾÷µ¥ÀÌÆ® ÇÔ¼ö¸¦ Á¤ÀÇ ÇÑ´Ù.

¼Ò¹®ÀÚ¸¦ ´ë¹®ÀÚ º¯È¯ÈÄ ÅؽºÆ®¸¦ Ãâ·ÂÇÏ´Â ¿¹Á¦ÀÌ´Ù.

class UpperCaseElement  extends HTMLElement {
 
  // 1. HTMLElement Ŭ·¡½º¸¦ »ó¼ÓÇÑ´Ù.
  constructor () {
    super ();
    this._text = null;
  }

  // 2. observedAttributes ¸Þ¼­µå¿¡¼­ °¨½ÃÇÒ ¼Ó¼ºÀ» ÁöÁ¤ ÇÑ´Ù.
  static get observedAttributes () {
    return [ "text"];
  }

  // 3. attributeChangedCallback °¨½ÃÇÒ ³»¿ë, UI¸¦ ¾÷µ¥ÀÌÆ® ÇÑ´Ù.
  attributeChangedCallback (name, oldValue, newValue) {
    this._text = newValue;
    this._updateRendering();
  }

  // 4. ¼Ó¼ºÀÇ set, get, ¾÷µ¥ÀÌÆ® ÇÔ¼ö¸¦ Á¤ÀÇ ÇÑ´Ù.
  get text () {
    return this._text;
  }
  set text (v) {
    this.setAttribute ( "text", v);
  }
  _updateRendering () {
    this.textContent = this._text.toUpperCase();
  }
}

1.  HTMLElement Ŭ·¡½º¸¦ »ó¼ÓÇÑ´Ù.
    »ý¼ºÀÚ¿¡¼­ ºÎ¸ðÀÇ »ý¼ºÀÚ¸¦ È£ÃâÇØ¾ß ÇÑ´Ù.

ºÎ¸ðÀÇ »ý¼ºÀÚ¸¦ È£ÃâÇϱâ À§ÇØ super() ½ÇÇàÇÑ´Ù.
»ç¿ëÇÒ ¼Ó¼ºÀ» null·Î ÃʱâÈ­ ÇÑ´Ù.

class UpperCaseElement  extends HTMLElement {
 
  constructor () {
    super ();
    this._text = null;
  }
  .....
}

2. observedAttributes ¸Þ¼­µå¿¡¼­  ¸ð´ÏÅÍÇÒ ¼Ó¼ºÀ» Á¤ÀÇÇÑ´Ù.
   ¼Ó¼ºÀÌ ¹Ù²î¸é attributeChangedCallback ¸Þ¼­µå°¡ È£ÃâµÈ´Ù.

°¨½ÃÇÒ ¼Ó¼ºÀ» ÁöÁ¤ÇÑ´Ù.
¼Ó¼ºÀÌ ¹Ù²î¸é attributeChangedCallback() ¸Þ¼­µå°¡ È£ÃâµÈ´Ù.

  static get observedAttributes () {
    return [ "text"];
  }

3. attributeChangedCallback ³»¿ë, UI¸¦ ¾÷µ¥ÀÌÆ® ÇÑ´Ù.

¼Ó¼ºÀÇ °ªÀ» º¯°æÇØÁÖ°í UI ·»´õ¸µÀÇ ³»¿ëÀ» ¾÷µ¥ÀÌÆ® ÇÑ´Ù.

  attributeChangedCallback (name, oldValue, newValue) {
    this._text = newValue;
    this._updateRendering();
  }

4. ¼Ó¼ºÀÇ set, get, ¾÷µ¥ÀÌÆ® ÇÔ¼ö¸¦ Á¤ÀÇ ÇÑ´Ù.

  get text () {
    return this._text;
  }
  set text (v) {
    this.setAttribute ( "text", v);
  }
  _updateRendering () {
    this.textContent = this._text.toUpperCase();
  }

set ¸Þ¼­µå¿¡¼­ "this._text = v" ´ë½Å  setAttribute ¸Þ¼­µå¸¦ ½ÇÇàÇÏ´Â ÀÌÀ¯´Â ¹«¾ùÀϱî?
setAttribute ¸Þ¼­µå¸¦ ½ÇÇàÇϸé attributeChangedCallback ¸Þ¼­µå°¡ È£ÃâµÇ±â ¶§¹®ÀÌ´Ù.

ÀÌ ¿Ü¿¡µµ ¿¤¸®¸ÕÆ®°¡ Ãß°¡ µÇ¾úÀ»¶§ connectedCallback, ¿¤¸®¸ÕÆ®°¡ Á¦°Å µÉ¶§ disconnectedCallback ¸Þ¼­µå°¡ ÀÖ´Ù.
connectedCallback () {
    this._updateRendering();
}

disconnectedCallback() {
}

2. customElements.defineÀ¸·Î Ä¿½ºÅÒ ¿¤¸®¸ÕÆ® Á¤ÀÇ

v0 ¹öÀü¿¡¼­´Â document.registerElement( )¸¦ »ç¿ëÇÑ´Ù.
v1 ¹öÀü¿¡¼­´Â window.customElements( )¸¦ »ç¿ëÇÑ´Ù.
Ä¿½ºÅÒ ¿¤¸®¸ÕÆ® À̸§Àº ¹Ýµå½Ã ÇÏÀÌÇ "-"ÀÌ Æ÷ÇÔ µÇ¾î¾ß ÇÑ´Ù. ÇÏÀÌÇÂÀÌ ¾øÀ¸¸é Ä¿½ºÅÒ ¿¤¸®¸ÕÆ®°¡ Á¤»óÀûÀ¸·Î ½ÇÇàÀÌ ¾ÈµÈ´Ù.

customElements.define ( "uppercase-element", UpperCaseElement);

Ä¿½ºÅÒ ¿ä¼Ò À̸§À» "uppercase-element"³ª "uppercase-conv"·Î ÁöÁ¤Çϸé Á¤»óÀûÀ¸·Î ½ÇÇàÀÌ µÇÁö¸¸  "uppercaseelement"·Î ÁöÁ¤Çϸé Á¤»óÀûÀ¸·Î ½ÇÇàÀÌ ¾ÈµÈ´Ù.

customElements.define(name, constructor, options)

name :  Ä¿½ºÅÒ ¿¤¸®¸ÕÆ®ÀÇ À̸§ÀÌ´Ù. ÇÏÀÌÇÂÀ» Æ÷ÇÔÇÏ°í ÀÖ¾î¾ß ÇÑ´Ù.
constructor :  »õ·Î¿î Ä¿½ºÅÒ ¿¤¸®¸ÕÆ®ÀÇ »ý¼ºÀÚ
options : ¿ä¼ÒÀÇ Á¤ÀÇ ¹æ¹ýÀ» Á¦¾îÇÏ´Â °´Ã¼·Î ÇöÀç Áö¿øµÇ´Â ¿É¼ÇÀº "extends" ÇϳªÀÌ´Ù.
   
"extends" ¿É¼ÇÀº ¾î¶² ³»Àå ¿É¼ÇÀ» È®ÀåÇß´ÂÁö ÁöÁ¤ÇÑ´Ù. HTMLButtonElement ó·³ ±âÁ¸ ³»Àå ¿ä¼Ò¸¦ È®ÀåÇßÀ»¶§ "extends" ¿É¼ÇÀ» ÁöÁ¤ÇÑ´Ù.

3. Ä¿½ºÅÒ ¿¤¸®¸ÕÆ® »ç¿ë

div¸¦ »ç¿ë ÇÏ´Â°Í Ã³·³ ¿ä¼Ò¸¦ »ç¿ëÇÏ¸é µÈ´Ù.
¿©±â¼­ ¼Ó¼ºÀÌ text¿¡ "hello world"¸¦ ÁöÁ¤ÇÏ°í ÀÖ´Ù.

<uppercase-element text = "hello world"> </uppercase-element>

°á°ú)
HELLO WORLD

Å×½ºÆ®: customelement_test.html

4. ±âº» ¿ä¼Ò È®Àå (customized built-in element)

±âº» ¿ä¼Ò¸¦ È®ÀåÇÑ Ä¿½ºÅÒ ¿¤¸®¸ÕÆ®µµ ¸¸µé¼ö ÀÖ´Ù.
¿©±â¼­´Â 'button' ¿ä¼ÒÀÎ HTMLButtonElement¸¦ È®ÀåÇØ º¸ÀÚ.

class ButtonCounter extends HTMLButtonElement {
  connectedCallback() {
    this.textContent = 0;
    this.addEventListener('click', this.increment);
  }
  increment(e) {
    e.currentTarget.textContent++;
  }
}

customElements.define( 'button-counter', ButtonCounter, {extends: 'button'});

±âº» ¿ä¼Ò¸¦ È®ÀåÇÑ Ä¿½ºÅÒ ¿ä¼Ò¸¦ ¸¸µé¶§ customElements.define( ) ÇÔ¼ö¿¡¼­ "{extends: 'button'}" ¿É¼ÇÀ» ¹Ýµå½Ã ÁöÁ¤ÇØ¾ß ½ÇÇàÀÌ µÈ´Ù.

ÀÚ¹Ù½ºÅ©¸³ new ¿¬»êÀÚ·Î °´Ã¼ »ý¼ºÇÏ´Â ¹æ¹ý

document.body.appendChild(
  new ButtonCounter()
);

HTML·Î °´Ã¼ »ý¼ºÇÏ´Â ¹æ¹ý

<button is="button-counter"></button>

"<button-counter></button-counter>" ó·³ Á¤ÀÇ ÇÏ¸é ½ÇÇàÀÌ ¾ÈµÈ´Ù.
±âº» ¿ä¼Ò¸¦ È®Àå ÇÒ¶§´Â is="" ¼Ó¼ºÀ» Ãß°¡ÇÏ¿© Ä¿½ºÅÒ ºôÆ®ÀÎ ¿ä¼Ò·Î ½ÇÇàÀÌ µÇµµ·Ï ÁöÁ¤ÇÑ´Ù.

is="" ±Û·Î¹ú ¼Ó¼ºÀº ±âº» ³»Àå ¿ä¼Ò°¡ Ä¿½ºÅÒ ºôÆ®ÀÎ ¿ä¼Òó·³ ½ÇÇàÀÌ µÇµµ·Ï ÁöÁ¤ÇÑ´Ù.

Å×½ºÆ® : custom_button_element.html

°á°ú)


Âü°í)
http://www.tohoho-web.com/ex/custom-elements.html
https://qiita.com/yoichiro6642/items/fdb8372bd8a68c754dc3

define ¼³¸í
https://developer.mozilla.org/en-US/docs/Web/API/CustomElementRegistry/define

is ¼³¸í
https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/is

HTMLButtonElement ¿¹Á¦
https://developers.google.com/web/fundamentals/web-components/customelements?hl=ko
https://www.webreflection.co.uk/blog/2016/08/21/custom-elements-v1
https://medium.com/dev-channel/the-case-for-custom-elements-part-2-2efe42ce9133