$30 off During Our Annual Pro Sale. View details »

The State of Web Components

Shogo Sensui
September 24, 2017

The State of Web Components

2017年9月24日に開催された HTML5 Conference 2017 の「The State of Web Components」のセッション資料です。

Shogo Sensui

September 24, 2017
Tweet

More Decks by Shogo Sensui

Other Decks in Technology

Transcript

  1. )5.-$POGFSFODF  4IPHP4FOTVJBLB!DI 5IF4UBUFPG8FC$PNQPOFOUT

  2. !DI

  3. ‣ 4IPHP4FOTVJ ‣ ؎ٝة٦طحزדכDIדׅ ‣ $ZCFS"HFOU *OD ‣ 8FC*OJUJBUJWF$FOUFS ‣

    4PGUXBSF&OHJOFFS ‣ 8FC䪮遭Ⰻ菙ָ㥨ֹדׅ ‣ 044崞⹛׮׃גתׅ
  4. 馄鸞劤ָ⳿תׅ 涪㡰✮㹀

  5. 8IZ8FC$PNQPOFOUT

  6. )5.- $44 8FCꟚ涪罏

  7. 8FCחֶֽ׷鿇ㅷךꨇ׃ׁ ‣ )5.-ה$44חأ؝٦فָ㶷㖈׃זְ ‣ 铣׫鴥׿׌$44ך䕦갟眔㔲ָ鎘׶濼׸זְ ‣ せ⵸瑞꟦ָ遼瑱׃זְ״ֲծ䌢ח䠐陎ׅ׷䗳銲ָ֮׷ ‣ ⡲׏׋鿇ㅷ׾ⱄⵃ欽׃חְֻ ‣

    )5.- $44 +BWB4DSJQU׾תה׭׷➬穈׫ָזְ ‣ תה׭׋鿇ㅷ׾ꂁ䋒ׅ׷ؒ؝ءأذيָזַ׏׋
  8. نةٝ׾⡲׷חכ˘ GBODZCVUUPO

  9. <button> fancy button </button> button { background: #0086b3; color: white;

    padding: 1em; border-radius: 0.5em; border: none; } )5.-ה$44׾剅ֽל0,
  10. GBODZCVUUPO

  11. GBODZCVUUPO GBODZCVUUPO

  12. <button class="a"> fancy button </button> <button class="b"> fancy button </button>

    button { color: white; padding: 1em; border-radius: 0.5em; border: none; } button.a { background: #0086b3; } button.b { background: #008080; }
  13. GBODZCVUUPO GBODZCVUUPO

  14. GBODZCVUUPO GBODZCVUUPO GBODZCVUUPO

  15. GBODZCVUUPO GBODZCVUUPO GBODZCVUUPO PWBM TRVBSF

  16. fancy button </button> <button class="b"> fancy button </button> <button class="c">

    fancy button </button> <button class="oval"> oval </button> <button class="square"> border-radius: 0.5em; border: none; } button.a { background: #0086b3; } button.b { background: #008080; } button.oval { ... }
  17. GBODZCVUUPO GBODZCVUUPO GBODZCVUUPO PWBM TRVBSF

  18. <fancy-button color="a"> fancy button </fancy-button> <fancy-button color="b"> fancy button </fancy-button>

    <fancy-button color="c"> fancy button </fancy-button> <oval-button>oval</oval-button> <square-button>square</square-button>
  19. 4IBEPX%0. $VTUPN&MFNFOUT 5FNQMBUFT )5.-*NQPSUT ˟׍׳׏ה⵸תד

  20. ˟䎃猧植㖈 4IBEPX%0. $VTUPN&MFNFOUT 5FNQMBUFT &4.PEVMFT

  21. 4IBEPX%0.

  22. 4IBEPX%0.הכ ‣ )5.-ծ$44ծ+BWB4DSJQUך䕦갟眔㔲׾ꣲ㹀ׅ׷ ‣ مأزהז׷銲稆חTIBEPX3PPU׾欰װ׃ծ׉ך⚥ד饯ֿ׷ֿה׾4IBEPX %0.ⰻח殅׭׷ ‣ 4IBEPX%0.㢩鿇ַ׵ך䕦갟׾ꣲ㹀ׅ׷ ‣ TIBEPX3PPUפך،ؙإأ׾ꣲ㹀涸ח׃ծ䮶׷莸ְ׾䬐⥂ׅ׷

    ‣ TIBEPX3PPUפ،ؙإأדֹ׷PQFOٌ٦سהծ黪倖ׅ׷DMPTFEٌ٦سָ֮׷
  23. const button = document.querySelector('button'); const shadowRoot = button.attachShadow({ mode: 'open'

    // or 'close' }); // readonly property console.log(button.shadowRoot); 4IBEPX%0.ך欰װ׃倯
  24. GBODZCVUUPO ⢽ִלְֲֲֿنةٝ

  25. <button> fancy button </button> ֲֿ剅ֽ׋׵ءٝفٕ˘ <style> button { background: #0086b3;

    color: white; padding: 1em; border-radius: 0.5em; border: none; }ɹ </style>
  26. <button> #shadow-root fancy button </button> <style> button { background: #0086b3;

    color: white; padding: 1em; border-radius: 0.5em; border: none; } </style> <button> <slot></slot> </button>
  27. <button> #shadow-root fancy button </button> <style> button { background: #0086b3;

    color: white; padding: 1em; border-radius: 0.5em; border: none; }ɹ </style> <button> <slot></slot> </button>
  28. <button> #shadow-root fancy button </button> <style> button { background: #0086b3;

    color: white; padding: 1em; border-radius: 0.5em; border: none; } </style> <button> <slot></slot> </button> 4DPQFE
  29. $VTUPN&MFNFOUT

  30. $VTUPN&MFNFOUTהכ ‣ 杝荈ך)5.-銲稆׾㹑鎉ׅ׷ ‣ )5.-ד㹑鎉涸חⵃ欽דֹ׷ ‣ %0."1*׾鸐ׄגㄏ⟀涸חⵃ欽דֹ׷ ‣ ⟣䠐ך䮶׷莸ְ׾㹀纏ׅ׷ ‣

    㹀纏ׁ׸׋ٓ؎ؿ؟؎ؙٕ׾ؿحؙׅ׷
  31. class FancyButton extends HTMLElement { constructor() { ... } connectedCallback()

    { ... } disconnectedCallback() { ... } attributeChangedCallback() { ... } adoptedCallback() { ... } } ؕأةي銲稆ٓ؎ؿ؟؎ؙٕ
  32. 䖞勻ך8FC鿇ㅷךⱄⵃ欽 ‣ 鿇ㅷ׾圓䧭ׅ׷)5.-׾鎸鶢ׅ׷ ‣ $44ח״׷أة؎ؚٔٝ׾黝欽ׅ׷ ‣ $44ؿ؋؎ٕ׾ٗ٦سׅ׷ծTUZMF銲稆׾剅ֻծFUD ‣ +BWB4DSJQUח״׷䮶׷莸ְ׾黝欽ׅ׷ ‣

    +BWB4DSJQUؿ؋؎ٕ׾ٗ٦سׅ׷ծTDSJQU銲稆׾剅ֻծFUD
  33. GBODZCVUUPO نةٝ׾⢪ְ׋ְ˘

  34. .fancy { background: #0086b3; color: white; padding: 1em; border-radius: 0.5em;

    border: none; } CVUUPODTT
  35. CVUUPOKT document .querySelector('.fancy') .addEventListener('click', () => { //... });

  36. <button class="fancy"> fancy button </button> JOEFYIUNM

  37. <link rel="stylesheet" href="button.css"> ... <button class="fancy"> fancy button </button> ...

    <script src="button.js"></script> 穈׫さ׻ׇג⢪ֲ
  38. None
  39. class FancyButton extends HTMLElement { connectedCallback() { this.innerHTML = `

    <style>button { … }</style> <button>fancy button</button> `; } } customElements .define('fancy-button', FancyButton);
  40. <fancy-button> fancy button </fancy-button> GBODZCVUUPO GBODZCVUUPO׾⢪ִ׷

  41. <fancy-button> <style> button { background: #0086b3; color: white; padding: 1em;

    border-radius: 0.5em; border: none; } </style> <button> fancy button </button> </fancy-button> /PUTDPQFE
  42. 4IBEPX%0.  $VTUPN&MFNFOUT

  43. class FancyButton extends HTMLElement { connectedCallback() { this.innerHTML = `

    <style>button { … }</style> <button>fancy button</button> `; } } customElements .define('fancy-button', FancyButton);
  44. class FancyButton extends HTMLElement { connectedCallback() { this.shadowRoot.innerHTML = `

    <style>button { … }</style> <button><slot></slot></button> `; } } customElements .define('fancy-button', FancyButton);
  45. <fancy-button> <style> button { background: #0086b3; color: white; padding: 1em;

    border-radius: 0.5em; border: none; } </style> <button> fancy button </button> </fancy-button>
  46. <fancy-button> #shadow-root <style> button { background: #0086b3; color: white; padding:

    1em; border-radius: 0.5em; border: none; } </style> <button> <slot></slot> </button> fancy button </fancy-button> 4DPQFE
  47. 5FNQMBUFT

  48. 5FNQMBUFTהכ ‣ ꬊ崞䚍ז)5.-銲稆׾㹑鎉ׅ׷ ‣ ذٝفٖ٦زה׃ג)5.-銲稆׾䪔ִ׷ ‣ 䖞勻ךعحؙ涸ז،فٗ٦ث׾ׇ׆ח幥׬

  49. <div style="display:none;"> <p>This is an image</p> <img src="foo.jpg" alt=""> </div>

    4FOEBSFRVFTU
  50. <script type="text/template"> <p>This is an image</p> <img src="foo.jpg" alt=""> </script>

    &WBMXJUIJOOFS)5.-
  51. <template> <p>This is an image</p> <img src="foo.jpg" alt=""> </template> *OFSU✨

  52. 4IBEPX%0.  $VTUPN&MFNFOUT  5FNQMBUFT

  53. class FancyButton extends HTMLElement { connectedCallback() { this.shadowRoot.innerHTML = `

    <style>button { … }</style> <button><slot></slot></button> `; } } customElements .define('fancy-button', FancyButton);
  54. <template> <style>button { … }</style> <button><slot></slot></button> </template> <script> class FancyButton

    extends HTMLElement { // ... } customElements .define('fancy-button', FancyButton); </script>
  55. <link rel="import" href="fancy-button.html"> <fancy-button> fancy button </fancy-button>

  56. )5.-*NQPSUT… IUUQTHJUIVCDPNXDXFCDPNQPOFOUTJTTVFTJTTVFDPNNFOU

  57. )5.-.PEVMFT… IUUQTHJTUHJUIVCDPN5BLBZPTIJ,PDIJGEDFEGECCEBGFGF

  58. import fancy from './fancy.html' as HTMLTemplateElement; export class FancyButton extends

    HTMLElement { connectedCallback() { this.attachShadow({ mode: 'open' }).appendChild(fancy.content.cloneNode(true)); } }
  59. &4.PEVMFT

  60. &4.PEVMFTהכ ‣ &4.PEVMFTךـٓؐؠ㹋鄲 ‣ TDSJQUUZQFˑNPEVMF˒ד+BWB4DSJQUؿ؋؎ٕ׾ٗ٦سׅ׷ ‣ TDSJQUOPNPEVMFדꬊ㼎䘔橆㞮׾罋䣁ׅ׷ ‣ &4.PEVMFTך/PEFKT㹋鄲 ‣

    NKT׾&4.PEVMFTך+BWB4DSJQUؿ؋؎ٕה׃גٗ٦سׅ׷
  61. export default class FancyButton { ... } GBODZCVUUPOKT

  62. import React from 'react'; import ReactDOM from 'react-dom'; import PropTypes

    from 'prop-types'; import FancyButton from './fancy-button.js'; JOEFYKT
  63. <script type="module"> import FancyButton from './fancy-button.js'; customElements .define('fancy-button', FancyButton); </script>

  64. 4IBEPX%0.  $VTUPN&MFNFOUT  &4.PEVMFT

  65. class FancyButton extends HTMLElement { connectedCallback() { this.attachShadow({ mode: 'open'

    }).innerHTML = ` <style>button { … }</style> <button><slot></slot></button> `; } } customElements .define('fancy-button', FancyButton);
  66. export default class FancyButton extends HTMLElement { connectedCallback() { this.attachShadow({

    mode: 'open' }).innerHTML = ` <style>button { … }</style> <button><slot></slot></button> `; } }
  67. <fancy-button> fancy button </fancy-button> <script type="module"> import FancyButton from './fancy-button.js';

    customElements .define('fancy-button', FancyButton); </script>
  68. 8FCחֶֽ׷鿇ㅷךꨇ׃ׁ ‣ )5.-ה$44חأ؝٦فָ㶷㖈׃זְ ‣ 铣׫鴥׿׌$44ך䕦갟眔㔲ָ鎘׶濼׸זְ ‣ せ⵸瑞꟦ָ遼瑱׃זְ״ֲծ䌢ח䠐陎ׅ׷䗳銲ָ֮׷ ‣ ⡲׏׋鿇ㅷ׾ⱄⵃ欽׃חְֻ ‣

    )5.- $44 +BWB4DSJQU׾תה׭׷➬穈׫ָזְ ‣ תה׭׋鿇ㅷ׾ꂁ䋒ׅ׷ؒ؝ءأذيָזַ׏׋
  69. 4IBEPX%0. $VTUPN&MFNFOUT &4.PEVMFT OQN ZBSO 8FCחֶֽ׷鿇ㅷךꨇ׃ׁ ‣ )5.-ה$44חأ؝٦فָ㶷㖈׃זְ ‣ 铣׫鴥׿׌$44ך䕦갟眔㔲ָ鎘׶濼׸זְ

    ‣ せ⵸瑞꟦ָ遼瑱׃זְ״ֲծ䌢ח䠐陎ׅ׷䗳銲ָ֮׷ ‣ ⡲׏׋鿇ㅷ׾ⱄⵃ欽׃חְֻ ‣ )5.- $44 +BWB4DSJQU׾תה׭׷➬穈׫ָזְ ‣ תה׭׋鿇ㅷ׾ꂁ䋒ׅ׷ؒ؝ءأذيָזַ׏׋
  70. 1PMZNFS4VNNJU JO$PQFOIBHFO

  71. #PXFSJTEFQSFDBUFE

  72. 6TFOQN ZBSO

  73. // fancy-button v1.0.0 customElements .define('fancy-button', FancyButton); // fancy-button v1.1.0 customElements

    .define('fancy-button', FancyButton); ZBSO׾⢪ֲץֹ椚歋 ☠ ⣛㶷ٌآُ٦ٕ׾ؿٓحزזخٔ٦ד鍑寸דֹ׷✨
  74. ‣ #SPXTFS4VQQPSU ‣ "DDFTTJCJMJUZ ‣ -PBE1FSGPSNBODF ‣ 3FOEFS1FSGPSNBODF

  75. 8FC$PNQPOFOUTTBOECPY IUUQTDIHJUIVCJPXFCDPNQPOFOUTTBOECPY

  76. ‣ #SPXTFS4VQQPSU ‣ "DDFTTJCJMJUZ ‣ -PBE1FSGPSNBODF ‣ 3FOEFS1FSGPSNBODF

  77. ✅ ✅ $VTUPN&MFNFOUTW 4IBEPX%0.W 5FNQMBUFT &4.PEVMFT ✅ ✅ ✅ ✅

    ✅ ✅ ✅ ✅ ✅ ✅ 䎃猧ـٓؐؠ؟ه٦ز
  78. 8FC$PNQPOFOUT JT BWBJMBCMFOPX PO UIFNPCJMFXFC✨

  79. None
  80. :PV5VCFJTCVJMU POUIFUPQPG1PMZNFS

  81. None
  82. 6TFXFCDPNQPOFOUTKT ‣ $VTUPN&MFNFOUTWךهٔؿ؍ٕ ‣ 4IBEZ%0.4IBEPX%0.ך%0."1*هٔؿ؍ٕ ‣ 4IBEZ$444IBEPX%0.ךأة؎ٕꟼ鸬هٔؿ؍ٕ ‣ )5.-*NQPSUT

  83. 8IZ4IBEZ%0.  ‣ %0.خٔ٦ך،ؙإ؟׾ⵖ䖴ׅ׷ךָꨇ׃ְ ‣ ぐ珏%0."1*װ/PEF-JTUךؒىُٖ٦زָꨇ׃ְ ‣ EPDVNFOUCPEZ瘝ך،ؙإ؟׾♳剅ֹדֹזְ ‣ ؝٦سꆀָ花㣐חז׷♳ծػؿؓ٦وٝأח׮䕦갟ׅ׷

    ‣ 4IBEZ%0."1*׾➜׃ג،ؙإأׇׁ׷ ‣ 㸜㹀䚍׾⥂׍אאծػؿؓ٦وٝأ׾⳿ׅ
  84. None
  85. 8FC$PNQPOFOUT JTBMTP BWBJMBCMFOPX PO UIFEFTLUPQXFC

  86. ‣ #SPXTFS4VQQPSU ‣ "DDFTTJCJMJUZ ‣ -PBE1FSGPSNBODF ‣ 3FOEFS1FSGPSNBODF

  87. "DDFTTJCJMJUZ ‣ 4IBEPX%0.ך)5.-׾،ؙإءـٕח ‣ 鸐䌢ך%0.ず圫חծإوٝذ؍ؙأ׾䠐陎ׅ׷ ‣ )5.-׌ֽד♶⼧ⴓז㜥さכծ8"*"3*"ד؟ه٦زׅ׷ ‣ 孡חז׷ךכأ؝٦فⰻפך،ؙإأ ‣

    4IBEPX%0.ָꪪ⳿ׁ׸גְ׷׌ֽ ‣ ،ؙإءؽٔذ؍ָ⡚ְ؝ٝه٦طٝز׾⢪ֲ㜥さכ˘
  88. <fancy-button> #shadow-root fancy button </fancy-button> <style> button { background: #0086b3;

    color: white; padding: 1em; border-radius: 0.5em; border: none; } </style> <button> <slot></slot> </button> &YQPTFE
  89. <fancy-button> #shadow-root fancy button </fancy-button> <style> div { background: #0086b3;

    color: white; padding: 1em; border-radius: 0.5em; border: none; } </style> <div role="button" tabindex="0"> <slot></slot> </div> &YQPTFE
  90. ‣ #SPXTFS4VQQPSU ‣ "DDFTTJCJMJUZ ‣ -PBE1FSGPSNBODF ‣ 3FOEFS1FSGPSNBODF

  91. -PBE1FSGPSNBODF ‣ TDSJQUח״׷؝ٝه٦طٝزךٗ٦س ‣ ؙٔؒأز侧כ)551ד֮׸ל孡ח׃ֺׅזֻג葺ְ ‣ ؝ٝه٦طٝزך+BWB4DSJQUؿ؋؎ٕכNJOJGZׅ׷ ‣ UZQFˑNPEVMF˒㾩䚍ח״׷EFGFSٗ٦س ‣

    ؔفءّٝדBTZOD㾩䚍׾➰♷דֹ׷
  92. TDSJQUח״׷ぐ珏ٗ٦س IUUQTIUNMTQFDXIBUXHPSHNVMUJQBHFTDSJQUJOHIUNMUIFTDSJQUFMFNFOU

  93. ثُ٦صؚٝه؎ٝز ‣ ٔا٦أ׾㙵׭鴥׬ךַٍؗحءُׅ׷ךַ ‣ 㙵׭鴥׫כ剑׮傍ֻٖٝتׁؚٔٝ׸׉ֲ׌ָծⴱ劍ٗ٦سָ曯暨חז׷ ‣ ׉׸״׶כ$BDIF$POUSPMقحتװ4FSWJDF8PSLFSזודٍؗحءُ׃׋ְ ‣ ⴱ劍ٗ٦س׾傍׭׋ְ ‣

    MJOLSFMˑQSFMPBE˒ד"5'חꟼ׻׷ٔا٦أ׾ٗ٦س׃גֶֻ ‣ 如㔐鼂獳ח䗳銲זٔا٦أכMJOLSFMˑQSFGFUDI˒דٗ٦س׃גֶֻ
  94. ‣ #SPXTFS4VQQPSU ‣ "DDFTTJCJMJUZ ‣ -PBE1FSGPSNBODF ‣ 3FOEFS1FSGPSNBODF

  95. 3FOEFS1FSGPSNBODF ‣ -JHIU%0.ה4IBEPX%0.ך䊴 ‣ 4IBEPX%0.׉ך׮ךךכـٓؐؠ㹋鄲ך剑黝⻉ח㨻י״ֲ ‣ ׋ע׿㣐䊴כזְ⦐➂ך✮䟝דׅ ‣ 7JSUVBM%0.ח״׷䊴ⴓ䲽歗ך⡭㖑 ‣

    ➙תד鸐׶3FBDUזוך7JFXٓ؎ـٓٔה穈׫さ׻ׇ׷ ‣ 8FC$PNQPOFOUTⰻד䊴ⴓ䲽歗׾㹋倵ׅ׷
  96. import React from 'react'; export default class Button extends React.Component

    { handleClick(e) { if (this.props.onClick) { this.props.onClick(e); } } render() { const handleClick = this.handleClick.bind(this); return ( <fancy-button onClick={handleClick}> {this.props.children} </fancy-button> ); } }
  97. 1PMZNFS-BCTMJUIUNM ‣ 5BHHFE5FNQMBUF-JUFSBMדUFNQMBUF׾⢪ֲ➬穈׫ ‣ IUNMAAדذٝفٖ٦ز׾⡲׶ծSFOEFS ד)5.-׾欰䧭ׅ׷ ‣ SFOEFS ד床ׅ⹛涸ז鿇ⴓך׫׾䊴ⴓ䲽歗ׅ׷

  98. const helloTemplate = (name) => html`<div>Hello ${name}!</div>`; // renders <div>Hello

    Steve!</div> to the document body render(helloTemplate('Steve'), document.body); // updates to <div>Hello Kevin!</div>, but only updates the ${name} part render(helloTemplate('Kevin'), document.body);
  99. import { html, render } from './lit-html.js'; export default class

    IconButton extends HTMLElement { connectedCallback() { this.attachShadow({ mode: 'open' }); render(this.template, this.shadowRoot); } get template() { return html` <style>...</style> <button> <i class="${this.getAttribute('icon')}"></i> <slot></slot> </button> `; } };
  100. תה׭ ‣ 8FC$PNQPOFOUTחꟼׅ׷ぐ珏➬圫ָ㸜㹀׃גֹ׋ ‣ ـٓؐؠ㹋鄲׮滠㹋ח鹌׫ծ暴חٌغ؎ٕ8FCדכه ٔؿ؍ٕז׃ד⢪ִ׷ ‣ ➙⢪׏גְ׷䪮遭أةحؙח׮《׶鴥׿דְֽ׷ ‣ ـٓؐؠⰻ鿇Ⳣ椚ך剑黝⻉׮䖉׍אאծطحزٙ٦ؙ

    ꟼ鸬כ㛇劤ח屟׏׋ثُ٦صؚٝד0,
  101. :PVBSFSFBEZUPVTF 8FC$PNQPOFOUT✨

  102. 5IBOLZPV !DI "DI