The State of Web Components

0d605a3350dd7e91b8136aecffd5ceeb?s=47 Shogo Sensui
September 24, 2017

The State of Web Components

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

0d605a3350dd7e91b8136aecffd5ceeb?s=128

Shogo Sensui

September 24, 2017
Tweet

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