ããã«ã¡ã¯ ããã³ããšã³ãéçºã§ã¯Webã³ã³ããŒãã³ãã䜿çšããŸãã ãã®èšäºã§ã¯ãWebã³ã³ããŒãã³ãã®ãã¹ãŠã®æ©èœãšãçŸåšã®äœ¿ç𿹿³ã«ã€ããŠããŸã é«åºŠãªãµããŒããèæ
®ããŠèª¬æããŸãã
Webã³ã³ããŒãã³ãã«ã€ããŠç°¡åã«èª¬æããŸããããã¯ãã©ã€ãã©ãªãè±ç«ãæ¥ç¶ããã«ãWebäžã®ã¹ã¿ã€ã«ãšã¹ã¯ãªããããã€ãã£ãã«ã«ãã»ã«åããã³ã³ããŒãã³ãã¢ãããŒãã䜿çšã§ãããã¯ãããžã®ã»ããã§ãã æšæºãéåžžã®ReactãŸãã¯Angularã®ä»£ããã«æäŸãããã®ã«èå³ããããå€ããã©ãŠã¶çšã«éçºãããšãã«ããã䜿çšããæ¹æ³ã«èå³ãããå Žåã¯ãcatãæ±ããŸãã

詳现ãªç ç©¶ã®ããã®è³æã®ãªã¹ãã¯ãèšäºã®æåŸã«ãããŸãã
å
容ïŒ
ãšã³ããªãŒ
ç§ã¯äž»èŠãªåœéãã£ã³ããŒã³ã®1ã€ã§ããã³ããšã³ããµãŒãã¹éçºè
ãšããŠåããŠãããçŸåšããããžã§ã¯ãã®ããã³ããšã³ãã2床ç®ã«æžãæããŠããŸãã
1C-Bitrixã®èŠç¯ã«åŸã£ãŠæžãããæåã®ããŒãžã§ã³ã§ã¯ãå€ãã®ãã³ãã¬ãŒãã®ã¹ã¯ãªãããšã¹ã¿ã€ã«ããã®èãç§ãåŸ
ã£ãŠããŸããã ãã¡ãããã¹ã¯ãªããã¯jQueryã§ãããã¹ã¿ã€ã«ã¯æ§é ãé åºããªããå®å
šã«æ··chaãšãããã®ã§ãã æ°ãããã©ãããã©ãŒã ãžã®ç§»è¡ã«é¢é£ããŠããããžã§ã¯ããå®å
šã«æžãçŽãæ©äŒããããŸããã ç§©åºãå埩ããããã«ãBEMææ³ã䜿çšããŠç¬èªã®ã³ã³ããŒãã³ãã·ã¹ãã ãéçºããŸããã ããŒã¯ã¢ããå
ã®BEMãããã¯ã®ã€ã³ã¹ã¿ã³ã¹ããšã«ãããŒãžã®èªã¿èŸŒã¿åŸã«ã察å¿ããã¯ã©ã¹ã®ãªããžã§ã¯ãã1ã€äœæãããããžãã¯ã®å¶åŸ¡ãéå§ãããŸãã ãããã£ãŠããã¹ãŠãéåžžã«å³å¯ã«ã·ã¹ãã åãããŠããŸã-ãããã¯ïŒããžãã¯ãšã¹ã¿ã€ã«ïŒã¯åå©çšå¯èœã§ãäºãã«åé¢ãããŠããŸãã
ãããžã§ã¯ãã®ãµããŒããšãã¡ã€ãã©ã€ãºã®1幎åŸããã®ãããªã·ã¹ãã ã®å€ãã®æ¬ ç¹ãæããã«ãªããŸããã ç§ã®æ¬äŒŒã³ã³ããŒãã³ããæ©èœããããŒã¯ã¢ããã¯ãéçºè
ã®æ³šæãšãæ£çŽãªèšèãã«åºã¥ããŠããŸããJSã¯ãã¬ã€ã¢ãŠãèšèšè
ãå¿
èŠãªãã¹ãŠã®èŠçŽ ãæ£ããé
眮ãããããã«ã¯ã©ã¹ãå²ãåœãŠãããšãæã¿ãŸãã ã³ã³ããŒãã³ããä»ã®BEMãããã¯ãå«ãDOMã倿ŽããããããŒã¯ã¢ãããajaxãä»ããŠããŒããããå Žåããã®ããŒã¯ã¢ããã®ã³ã³ããŒãã³ãã¯æåã§åæåããå¿
èŠããããŸãã äºäººç®ããããžã§ã¯ãã«ç»å ŽãããŸã§ãããã¯ãã¹ãŠæ¯æ¥ã®äœæ¥ã§ç°¡åã«èŠããŸããã æ®å¿µãªãããããã¥ã¡ã³ãã¯éåžžã«èšå€§ã§ããããåºæ¬çãªååã®ã¿ãã«ããŒããŠããŸããïŒãã®å Žåã®ããªã¥ãŒã ã¯ãã€ãã¹ã§ããïŒã 人çã§ã¯ãå·Šãžã®ã¹ããããŸãã¯å³ãžã®ã¹ãããããåçããæã¡ç Žãã宿ããã³ã³ããŒãã³ããèªãããšã¯æ··ä¹±ããã ãã§ããã
ãã®ãã¹ãŠãšãSPA / PWAãžã®èšç»çãªç§»è¡äžã®éçºäžã®åé¡ã®æ°ã®æœåšçãªå¢å ã«å ããŠãåç·ã®å¥ã®åèšèšãä¿ãããŸããã ãšãããç§ã®ã³ã³ããŒãã³ãã·ã¹ãã ã§ããèªè»¢è»ã¯ãäœãïŒç§ã®å Žåã¯JSïŒãåŠç¿ããéã«éåžžã«åœ¹ç«ã¡ãŸãããè€æ°ã®éçºè
ãããé«å質ã®ãããžã§ã¯ãã§ã¯ãããä¿¡é Œæ§ãé«ãæ§é åããããã®ãå¿
èŠã§ãã çŸåšïŒãã ããé·ãéïŒWebã«ã¯å€ãã®ãã¬ãŒã ã¯ãŒã¯ããããŸããããã®äžããéžæãããã®ããããŸãïŒPreactã¯ãæ¢ã«ããªãã¿ã®Reactãšéçºã«ãããŠãµã€ãºãå°ãããæå€§ã®é¡äŒŒæ§ãæäŸããŸããè§ãæ²ãã£ããšããããããã®ã·ã³ãã«ããªã©ãèªã£ãŠããŸãã æšæºã¯éç«ã£ãŠããŸãïŒæ¢ã«èšè¿°ãããããŒã¯ã¢ããã«äººçºçã«ïŒBEMããã³è¿œå ã®JSã«ãã£ãŠïŒãªã³ã¯ããå¿
èŠã®ãªãã¯ã€ã€ãŒãããžãã¯ãšã¹ã¿ã€ã«ã䜿çšããŠãåå©çšå¯èœãªWebã³ã³ããŒãã³ããäœæã§ããããšãããããŸãã ãããŠããããã¯ãã¹ãŠç®±ããåºããŠåäœããã¯ãã§ãã å¥è·¡ã§ããã
ç§ã®æšæºã«å¯ŸããåŒ·ãææ
ãšæããæªæ¥ãžã®ä¿¡å¿µãããã³æ¢åã®ã³ã³ããŒãã³ãã·ã¹ãã ãšWebã³ã³ããŒãã³ãïŒå€ç«ããããžãã¯ãæã€1ã€ã®ãã³ã³ããŒãã³ããã«å¯Ÿãã1ã€ã®JSã¯ã©ã¹ïŒã®é¡äŒŒæ§ã«ãããWebã³ã³ããŒãã³ãã䜿çšããããšã«ããŸããã æãåä»ãªããšã¯ããã©ãŠã¶ãŒã§ã®ãã®ããžãã¹ã®ãµããŒãã§ãã.Webã³ã³ããŒãã³ãã¯è¥ãããŠãå¹
åºããã©ãŠã¶ãŒãã«ããŒã§ãããåžè²©è£œåïŒAndroid 4.4ã¹ããã¯ãã©ãŠã¶ãŒãInternet Explorer 11ãªã©ïŒã§ãµããŒãããå¿
èŠããããã©ãŠã¶ãŒãã«ããŒã§ããŸããã ç§ã«æåŸ
ãããããçšåºŠã®çã¿ãšå¶éãããã³éçºã«é©åããããšã«åæãããã¬ãŒã ã¯ãŒã¯ã¯ç²Ÿç¥çã«åãå
¥ããããç§ã¯çè«ãšå®è·µçå®éšã®ç ç©¶ã«çªå
¥ããŸããïŒãŠã§ãã³ã³ããŒãã³ãã®ããã³ããæžãããããçç£ã«ããŒã«ããæ¹æ³ããŸããããŸããã
èšäºãèªãããã«å¿
èŠãªçè«äžã®æå°ïŒDOMããªãŒã§ã®åºæ¬çãªæäœã®ã¬ãã«ã§ã®çŽç²ãªJavaScriptãES2015ã®ã¯ã©ã¹ã®æ§æã®çè§£ãããã«React.js / Angular / Vue.jsã«ããŽãªãŒã®ãã¬ãŒã ã¯ãŒã¯ã®ãããããçç¥ããŠããããš
çè«
埩ç¿
Webã³ã³ããŒãã³ãã¯ã宣èšçã«èšè¿°ãããåå©çšå¯èœãªããŠã£ãžã§ãããããç¬èªã®ã¿ã°ã®åœ¢åŒã§åé¢ãããã¹ã¿ã€ã«ãšã¹ã¯ãªããã§äœæã§ããäžé£ã®æšæºã§ãã æšæºã¯ç¬ç«ããŠéçºãããæ¡ä»¶ä»ãã§ã¯ãªãWebã³ã³ããŒãã³ãã«ãªã³ã¯ãããŸã-ååãšããŠãåå¥ã«äœ¿çšãããåãã¯ãããžãŒã䜿çšã§ããŸãã ããããæ£ç¢ºã«çµã¿åããããšæã广çã§ãã
éåžžã4ã€ã®æšæºïŒã«ã¹ã¿ã èŠçŽ ãã·ã£ããŠDOMãHTMLãã³ãã¬ãŒããããã³HTMLã€ã³ããŒãïŒã¯ãã¹ãŠåå¥ã«èæ
®ãããçµåãããŸãã åå¥ã«æçšæ§ãäœããããæšæºã®ãã¹ãŠã®å¯èœæ§ã环ç©çã«æ€èšãã以åã«ç ç©¶ãããã®ã«è¿œå ããŸãã
Webã³ã³ããŒãã³ãã¯ããªãæ°ããæè¡ã§ãããæšæºã«ã¯å€ãã®å€æŽãå ããããŠããããšãæãåºããŠãã ããã ç§ãã¡ã«ãšã£ãŠãããã¯äž»ã«ã«ã¹ã¿ã èŠçŽ ãšã·ã£ããŠDOMæšæºã®ããã€ãã®ããŒãžã§ã³v0ããã³v1衚çŸãããŠããŸãã çŸåšã v0ã¯é¢ä¿ãããŸããã v1ã®ã¿ãæ€èšããŸãã 远å ã®è³æãæ€çŽ¢ãããšãã¯æ³šæããŠãã ããïŒ v1ããŒãžã§ã³ã¯2016幎ã«ã®ã¿åœ¢æãããŸãããã€ãŸãã2016幎ãŸã§ã®ãã¹ãŠã®èšäºãšãããªã¯ã仿§ã®å€ãããŒãžã§ã³ã«ã€ããŠè©±ãããšãä¿èšŒãããŠããŸãã
ã«ã¹ã¿ã èŠçŽ
ã«ã¹ã¿ã èŠçŽ ã¯ãããšãã°<youtube-player src=""></youtube-player>ãŸãã¯<yandex-map lat="34.86974" lon="-111.76099" zoom="7"></yandex-map>ããã«ãä»»æã®ååãšåäœãæã€æ°ããHTMLã¿ã°ãäœæããæ©èœ<yandex-map lat="34.86974" lon="-111.76099" zoom="7"></yandex-map> ã
ã«ã¹ã¿ã ã¢ã€ãã ãç»é²ãã
ãã¡ãããç¬èªã®ã¿ã°ããäœæãã§ããŸãïŒããšãã°ããã©ãŠã¶ãŒã¯<noname></noname>ãæ£ããåŠçããŸãïŒããåæã«èŠçŽ ã¯DOMããªãŒã®HTMLUnknownElementã¯ã©ã¹ã®ãªããžã§ã¯ããšããŠç»é²ãããããã©ã«ãã®åäœã¯ãããŸããã ãã®ãããªåèŠçŽ ãæåã§ã埩掻ããããå¿
èŠããããŸãã
ã«ã¹ã¿ã èŠçŽ ã®ä»æ§ã«ãããã©ã€ããµã€ã¯ã«ã«åŸã£ãŠæ°ããã¿ã°ãç»é²ãããã®åäœãèšå®ã§ããŸã-äœæãDOMãžã®æ¿å
¥ã屿§ã®å€æŽãDOMããã®åé€ã æ°ããHTMLæšæºã¿ã°ãšã«ã¹ã¿ã ã¿ã°ã®ç«¶åãé²ããããåŸè
ã®ååã«ã¯å°ãªããšã1ã€ã®ãã€ãã³ãå«ãŸããŠããå¿
èŠããããŸããããšãã°ã <custom-tag></custom-tag>ãŸãã¯<my-awesome-tag></my-awesome-tag> ã ãŸãããŠãŒã¶ãŒã¿ã°ã¯çŸåšãèªå·±çµäºããããšã¯ã§ããŸãããã³ã³ãã³ãã®ãªãã¿ã°ã§ãã£ãŠããã¢ã«ããå¿
èŠããããŸãã
åŠç¿ããããã®æè¯ã®æ¹æ³ã¯å®è·µã§ãããããæ©èœã<summary>èŠçŽ ã«äŒŒãèŠçŽ ãèšè¿°ããŸãã <x-spoiler>ãšåŒã³ãŸãããã
ãã®ãããªèŠçŽ ãDOMããªãŒã«è¿œå ããããšããã®èŠçŽ ã¯HTMLUnknownElementã¯ã©ã¹ã®ãªããžã§ã¯ãã«ããªããŸãã èŠçŽ ãã«ã¹ã¿ã èŠçŽ ãšããŠç»é²ãã customElementsåäœã远å ããã«ã¯ãã°ããŒãã«customElementsãªããžã§ã¯ãã®defineã¡ãœããã䜿çšããå¿
èŠããããŸãã æåã®åŒæ°ã¯ã¿ã°åã§ã2çªç®ã¯åäœã説æããã¯ã©ã¹ã§ãã ãã®å Žåãã¯ã©ã¹ã¯HTMLElementã¯ã©ã¹ãæ¡åŒµããŠãèŠçŽ ãä»ã®HTMLèŠçŽ ã®ãã¹ãŠã®åè³ªãšæ©èœãæã€HTMLElementããŸãã åèšïŒ
class XSpoiler extends HTMLElement {} customElements.define("x-spoiler", XSpoiler);
ãã®åŸããã©ãŠã¶ã¯ããŒã¯ã¢ããå
ã®ãã¹ãŠã®x-spoilerã¿ã°ãXSpoilerã§ã¯ãªãHTMLUnknownElementã¯ã©ã¹ã®ãªããžã§ã¯ããšããŠåäœæããŸãã innerHTML ã insertAdjacentHTML ã appendãŸãã¯HTMLãæäœããããã®ä»ã®ã¡ãœãããä»ããŠããã¥ã¡ã³ãã«è¿œå ããããã¹ãŠã®æ°ããx-spoilerã¿ã°ã¯ã XSpoilerã¯ã©ã¹ã«åºã¥ããŠããã«äœæãããŸãã document.createElement䜿çšããŠããã®ãããªDOMèŠçŽ ãäœæããããšãã§ãdocument.createElement ã
ç»é²æžã¿ã®ååã§ããŸãã¯ç»é²æžã¿ã®ã¯ã©ã¹ã«åºã¥ããŠèŠçŽ ãç»é²ããããšãããšãäŸå€ãçºçããŸãã
ã¿ã°åãšã¯ã©ã¹åã¯ãŸã£ããäžèŽããå¿
èŠã¯ãããŸããã ãããã£ãŠãå¿
èŠã«å¿ããŠãç°ãªãã¿ã°ã®äžã«åãã¯ã©ã¹åãæã€2ã€ã®ãŠãŒã¶ãŒèŠçŽ ãç»é²ã§ããŸãã
ããã§ããŠãŒã¶ãŒèŠçŽ ã¯ãã¡ããç»é²ãããŸããããæçšãªããšã¯äœããããŸããã ã«ã¹ã¿ã èŠçŽ ãæ¬åœã«æŽ»æ°ä»ããããã«ããã®ã©ã€ããµã€ã¯ã«ãèæ
®ããŠãã ããã
ãŠãŒã¶ãŒèŠçŽ ã®ã©ã€ããµã€ã¯ã«
ã³ãŒã«ããã¯ã¡ãœããã远å ããŠèŠçŽ ãäœæããDOMã«è¿œå ãã屿§ã倿ŽããDOMããèŠçŽ ãåé€ããŠã芪ããã¥ã¡ã³ãã倿Žã§ããŸãã ããã䜿çšããŠãã¹ãã€ã©ãŒã®ããžãã¯ãå®è£
ããŸããã³ã³ããŒãã³ãã«ã¯ãããã¹ããCollapseã/ãExpandããå«ããã¿ã³ãšãã¿ã°ã®å
ã®ã³ã³ãã³ããå«ãã»ã¯ã·ã§ã³ãå«ãŸããŸãã ã»ã¯ã·ã§ã³ã®å¯èŠæ§ã¯ããã¿ã³ãŸãã¯å±æ§å€ãã¯ãªãã¯ããããšã§å¶åŸ¡ãããŸãã ãã¿ã³ããã¹ãã¯ã屿§ã«ãã£ãŠã«ã¹ã¿ãã€ãºããããšãã§ããŸãã
èŠçŽ ãäœæããããã®ã³ãŒã«ããã¯ã¯ãã¯ã©ã¹ã®ã³ã³ã¹ãã©ã¯ã¿ãŒã§ãã æ£ããåäœãããããã«ã¯ãæåã«superçµç±ã§èŠªã³ã³ã¹ãã©ã¯ã¿ãŒãåŒã³åºãå¿
èŠããããŸãã ã³ã³ã¹ãã©ã¯ã¿ãŒã§ã¯ãããŒã¯ã¢ããã®èšå®ãã€ãã³ããã³ãã©ãŒã®ãã³ã°ããã®ä»ã®æºåäœæ¥ãè¡ãããšãã§ããŸãã ã³ã³ã¹ãã©ã¯ã¿ãŒã§ã¯ãä»ã®ã¡ãœãããšåæ§ã«ã thisã¯DOMèŠçŽ èªäœãåç
§ããã«ã¹ã¿ã èŠçŽ ãHTMLElementæ¡åŒµãããšããäºå®ã«ããã thisã¯querySelectorãªã©ã®ã¡ãœãããšquerySelectorãªã©ã®ããããã£ããããŸãã
ãã¿ã³ããã¹ãã®å€ãã³ã³ã¹ãã©ã¯ã¿ãŒã®ã³ã³ããŒãã³ãããŒã¯ã¢ããã远å ãã opened屿§ã®ååšã倿Žãããã³ãã©ãŒããã¿ã³ã«ã¢ã¿ããopenedãŸãã
class XSpoiler extends HTMLElement { constructor() { super(); this.text = { "when-close": "", "when-open": "", } this.innerHTML = ` <button type="button">${this.text["when-close"]}</button> <section style="display: none;">${this.innerHTML}</section> `; this.querySelector("button").addEventListener("click", () => { const opened = (this.getAttribute("opened") !== null); if (opened) { this.removeAttribute("opened"); } else { this.setAttribute("opened", ""); } }); } }
ã³ã³ã¹ãã©ã¯ã¿ãŒã®åéšåã詳现ã«åæããŸãã
super()ã¯ã HTMLElementã¯ã©ã¹ã®ã³ã³ã¹ãã©ã¯ã¿ãŒãåŒã³åºãHTMLElement ã ãã®å ŽåãèŠçŽ ã³ã³ã¹ãã©ã¯ã¿ãŒãå¿
èŠãªå Žåãããã¯å¿
é ã¢ã¯ã·ã§ã³ã§ãã
this.text thisã¯ãªããžã§ã¯ããªã®ã§ãç¬èªã®ããããã£ã远å ã§ããŸãã ãã®å Žåããã¿ã³ã«è¡šç€ºãããtextãªããžã§ã¯ãã«è£å©ããã¹ããä¿åããŸãã
this.innerHTML ãDOMèŠçŽ ã®ããŒã¯ã¢ããthis.innerHTMLèšå®ããŸãã ããããéã«ãå°ãé«ãããã¹ãã䜿çšããŸãã
this.querySelector("button").addEventListenerã¯ã opened屿§ãèšå®ãŸãã¯ã¯ãªã¢ãããã¿ã³ã®clickã€ãã³ããã³ãã©ãŒã远å openedãŸãã è«çå€ãšããŠäœ¿çšããŸã-ã¹ãã€ã©ãŒã¯éããŠãããéããŠããããã屿§ã¯ååšãããããªããã®ã©ã¡ããã§ãã ãã³ãã©ãŒã§ã¯ã nullãšã®æ¯èŒãéããŠå±æ§ã®ååšã確èªãã屿§ãèšå®ãŸãã¯åé€ããŸãã
äœæããããã¿ã³ãã¯ãªãã¯ãããšã opened屿§ã倿ŽãããŸãã ãããŸã§ã®ãšããã屿§ã倿ŽããŠãäœãèµ·ãããŸããã ãã®ãããã¯ã«é²ãåã«ãã³ãŒããå°ã倿ŽããŸãã
<button>ã¯ããã¿ã³ãç¡å¹ã«ããdisabled屿§ãããããšã«æ³šæããŠãã ããã ããŒã¯ã¢ããã«æžã蟌ããšããã¿ã³ã¯ã¢ã¯ãã£ãã§ãªããªããåé€ãããšåã³ã¯ãªãã¯å¯èœã«ãªããŸãã getAttribute ã setAttribute ãããã³removeAttributeã¡ãœããã䜿çšããŠãJavaScriptã³ãŒãã®å±æ§ãæäœããããšãã§ããŸãã ããããããã¯ããŸã䟿å©ã§ã¯ãããŸããã屿§ãæäœããã«ã¯3ã€ã®ã¡ãœãããå¿
èŠã§ãããããã¯é·ããããã«æååã®ã¿ã§æ©èœããŸãïŒå±æ§ã®å€ã¯åžžã«æååã§ãïŒã ãããã£ãŠãDOMèŠçŽ ã¯ãå€ãã®å Žåãåãååã®ããããã£ã®å±æ§ã®ããªãã¬ã¯ã·ã§ã³ãã䜿çšããŸãã ãã®ããã button.disabledããããã£ã¯å±æ§ã®æç¡ãè¿ããŸãã æ¬¡ã«ã屿§ã䜿çšããçŽæ¥äœæ¥ãšããããã£ã䜿çšãã2ã€ã®ã¢ãããŒããæ¯èŒããŸãã
åæããŠãããããã£ãæäœããæ¹ãã¯ããã«äŸ¿å©ã§ããïŒ å±æ§ãopenedãç¶æ
ã§åãã¡ã«ããºã ãå®è£
ãããã®å€ãç°¡åã«ååŸããŠèšå®ã§ããããã«ããŸãã ãããè¡ãããã«ãã¯ã©ã¹å
ã®ããããã£ã®ã²ãã¿ãŒãšã»ãã¿ãŒã®æ©èœã䜿çšããŸãã
class XSpoiler extends HTMLElement { constructor() { super(); this.text = { "when-close": "", "when-open": "", } this.innerHTML = ` <button type="button">${this.text["when-close"]}</button> <section style="display: none;">${this.innerHTML}</section> `; this.querySelector("button").addEventListener("click", () => { this.opened = !this.opened; }); } get opened() { return (this.getAttribute("opened") !== null); } set opened(state) { if (!!state) { this.setAttribute("opened", ""); } else { this.removeAttribute("opened"); } } }
æååããããã£ã®å ŽåïŒèŠçŽ ã®ã€ã³ã©ã€ã³idããªã³ã¯ã®hrefãªã©ïŒãã²ãã¿ãŒãšã»ãã¿ãŒã¯å°ãã·ã³ãã«ã«èŠããŸãããã¢ã€ãã¢ã¯æ®ããŸãã
ãŸãããã®ãããªããªãã¬ã¯ã·ã§ã³ããããã©ãŒãã³ã¹ã®ç¹ã§å¿
ãããæçšã§ã¯ãªãå Žåãããããšã远å ã§ããŸãã ããšãã°ããã©ãŒã èŠçŽ ã§ã¯ã value屿§ã®åäœãç°ãªããŸãã
ããã§å±æ§ãã§ããŸããããã¿ã³ãã¯ãªãã¯ãããšãã®å€ã倿Žã§ããŸããããã以äžã®æçšãªã¢ã¯ã·ã§ã³ã¯çºçããŸããã èŠçŽ ãé衚瀺ã«ããŠã¯ãªãã¯ãã³ãã©ã«çŽæ¥è¡šç€ºããããã®äŸ¿å©ãªã³ãŒãã远å ã§ããŸãããããšãã°ãå¥ã®å€éšJSã³ãŒãã§èŠçŽ ã®å¯èŠæ§ã倿Žããã®ã¯éåžžã«å°é£ã§ãã
代ããã«ã attributeChangedCallbackã¡ãœããã䜿çšããŠããã³ãã©ãŒãã¢ã¿ããããŠå±æ§å€ã倿Žã§ãattributeChangedCallback ã ããã¯ã屿§ã倿Žããããã³ã«åŒã³åºãããããã屿§ã䜿çšããŠãå
éšãšå€éšã®äž¡æ¹ããã³ã³ããŒãã³ããå¶åŸ¡ã§ããŸãã
ãã®ã¡ãœããã¯ã屿§åãå€ãå€ãæ°ããå€ã®3ã€ã®ãã©ã¡ãŒã¿ãŒã䜿çšããŸãã ãã®ã¡ãœãããåŒã³åºããŠçµ¶å¯Ÿã«ãã¹ãŠã®å±æ§ã倿Žããããšã¯ããã©ãŒãã³ã¹ã®èгç¹ããã¯éåççã§ãããããçŸåšã®ã¯ã©ã¹ã®observedAttributeséçé
åã«ãªã¹ããããŠããããããã£ã倿Žããå Žåã«ã®ã¿æ©èœããŸãã
ãã®ã³ã³ããŒãã³ãã¯ã3ã€ã®å±æ§ïŒ opened ã text-when-open ã text-when-closeã®å€æŽã«å¿çããå¿
èŠãããtext-when-close ã æåã¯ã¹ãã€ã©ãŒã®è¡šç€ºã«åœ±é¿ããä»ã®2ã€ã¯ãã¿ã³ã®ããã¹ããå¶åŸ¡ããŸãã ãŸãããããã®å±æ§ã®ååãobservedAttributeséçé
åã«è¿œå ããŸãã
static get observedAttributes() { return [ "opened", "text-when-open", "text-when-close", ] }
次ã«ã attributeChangedCallbackã¡ãœããèªäœã远å ãattributeChangedCallback ãããã¯ã倿Žããã屿§ã«å¿ããŠãã³ã³ãã³ãã®å¯èŠæ§ã倿ŽããŠãã¿ã³ããã¹ãã衚瀺ããããå¿
èŠã«å¿ããŠãã¿ã³ããã¹ãã倿ŽããŠè¡šç€ºããŸãã ãããè¡ãã«ã¯ãã¡ãœããã®æåã®åŒæ°ã§switchã䜿çšããŸãã
attributeChangedCallback(attrName, oldVal, newVal) { switch (attrName) { case "opened": const opened = newVal !== null; const button = this.querySelector("button"); const content = this.querySelector("section"); const display = opened ? "block" : "none"; const text = this.text[opened ? "when-open" : "when-close"]; content.style.display = display; button.textContent = text; break; case "text-when-open": this.text["when-open"] = newVal; if (this.opened) { this.querySelector("button").textContent = newVal; } break; case "text-when-close": this.text["when-close"] = newVal; if (!this.opened) { this.querySelector("button").textContent = newVal; } break; } }
attributeChangedCallbackã¡ãœããã¯ãå¿
èŠãªå±æ§ãæåã«èŠçŽ ã«ååšããå Žåã§ãæ©èœããããšã«æ³šæããŠãã ããã ã€ãŸãã opened屿§ã䜿çšããŠã³ã³ããŒãã³ããããŒã¯ã¢ããã«ããã«æ¿å
¥ãããšãã¹ãã€ã©ãŒãå®éã«éãããŸãã attributeChangedCallbackã¯ã constructorçŽåŸã«æ©èœããŸãã ãããã£ãŠãã³ã³ã¹ãã©ã¯ã¿ãŒã§å±æ§ã®åæå€ãåŠçããããã«è¿œå ã®äœæ¥ã¯å¿
èŠãããŸããïŒãã¡ããã屿§ã远跡ãããªãéãïŒã
ããã§ãã³ã³ããŒãã³ããå®éã«æ©èœããŸãïŒ ãã¿ã³ãã¯ãªãã¯ãããšã opened屿§ã®å€ãå€åãããã®åŸattributeChangedCallbackã³ãŒã«ããã¯ãããªã¬ãŒãããã³ã³ãã³ãã®å¯èŠæ§ãå¶åŸ¡ãããŸãã 屿§ãšattributeChangedCallbackç¶æ
管çã«ãããåæç¶æ
ïŒãªãŒãã³ã¹ãã€ã©ãŒã衚瀺ããå Žåã¯ããŒã¯ã¢ããã«openã远å ã§ããŸãïŒãå¶åŸ¡ããããå€éšããç¶æ
ã管çãããã§ããŸãïŒä»ã®JSã³ãŒãã§èŠçŽ ã®å±æ§ãèšå®ãŸãã¯åé€ã§ããããã¯æ£ããåŠçãããŸãïŒ ã ããŒãã¹ãšããŠãã³ã³ãããŒã«ãã¿ã³ã®ããã¹ããã«ã¹ã¿ãã€ãºã§ããŸãã çµæã®ãã¢ã¯ã æ°é®®ãªChromeã§èŠãŠãã ããïŒ
äž»ãªæ©èœã®æºåãæŽããŸããããããã¯ãã«ã¹ã¿ã èŠçŽ ã®æãäžè¬çã«äœ¿çšãããæ©èœã§ãã æ¬¡ã«ã䜿çšé »åºŠã®äœãã³ãŒã«ããã¯ã«ã€ããŠæ€èšããŸãã
connectedCallbackã¡ãœãããããªã¬ãŒãããDOMããªãŒã«èŠçŽ ãæ¿å
¥ãããŸãã ç»é²æã«èŠçŽ ããã§ã«ããŒã¯ã¢ããã«ãã£ãå ŽåããŸãã¯HTMLæååãæ¿å
¥ããŠäœæãããå Žåã constructorã¯å¿
èŠã«å¿ããŠé çªã«æ©èœãattributeChangedCallback ãæ¬¡ã«connectedCallback ã ãã®ã³ãŒã«ããã¯ã¯ãããšãã°ãDOMããªãŒã®èŠªã«é¢ããæ
å ±ãç¥ãå¿
èŠãããå ŽåããŸãã¯èŠçŽ ã䜿çšããçŽåã«ã³ã³ããŒãã³ããæé©åããéãã³ãŒããå»¶æããå Žåã«äœ¿çšã§ããŸãã ãã ããçæãã¹ã2ã€ã®ç¹ããããŸãã1ã€ã¯ã constructorã1ã€ã®èŠçŽ ã«å¯ŸããŠ1åèµ·åããå Žåããã®åŸãèŠçŽ ãDOMã«æ¿å
¥ããããã³ã«connectedCallbackèµ·åããããšã§ããã³ã³ã¹ãã©ã¯ã¿ãŒããconnectedCallback ãããã¯ãšã©ãŒã«ã€ãªããå¯èœæ§ããããŸãã ãã®ã¡ãœããã¯ãã€ãã³ããã³ãã©ãŒã®å²ãåœãŠãããµãŒããŒãžã®æ¥ç¶ãªã©ã®ãã®ä»ã®è² è·ã®é«ãæäœã«äœ¿çšã§ããŸãã
DOMã§ã®èŠçŽ ã®æ¿å
¥ã远跡ã§ããããã«ãåé€ã远跡ã§ããŸãã disconnectedCallbackã¡ãœããããããæ
åœããŸãã ããšãã°ã remove()ã¡ãœããã䜿çšããŠDOMããèŠçŽ ãåé€ãããå Žåã«æ©èœããŸãã æ³šïŒèŠçŽ ãDOMããªãŒããåé€ãããŠãããããã®èŠçŽ ãžã®ãªã³ã¯ãããå Žåã¯ãåã³DOMã«æ¿å
¥ã§ãã connectedCallbackãåã³æ©èœããŸãã åé€ããå Žåãããšãã°ãã³ã³ããŒãã³ãå
ã®ããŒã¿ã®æŽæ°ã忢ããããã¿ã€ããŒãåé€ãããã connectedCallbackã«å²ãåœãŠãããã€ãã³ããã³ãã©ãŒãåé€ãããããµãŒããŒãžã®æ¥ç¶ãéãããã§ããŸãã disconnectedCallbackã¯ã³ãŒãã®å®è¡ãä¿èšŒããªãããšã«æ³šæããŠãã ãã-ããšãã°ããŠãŒã¶ãŒãããŒãžãéãããšããã¡ãœããã¯åŒã³åºãããŸããã
æããŸãã«äœ¿çšãããã³ãŒã«ããã¯ã¯ã adoptedCallbackã¡ãœããã§ãã èŠçŽ ãownerDocumentããããã£ã倿Žãããšèµ·åããŸãã ããã¯ãããšãã°ãæ°ãããŠã£ã³ããŠãäœæããŠããã«ã¢ã€ãã ãç§»åããå Žåã«çºçããŸãã
ãŠãŒã¶ãŒèŠçŽ ã®çžäºäœçš
ãã§ã«çè§£ããããã«ãã³ã³ããŒãã³ãã¯å±æ§ã®å€ã«ãã£ãŠçŽæ¥ãŸãã¯ããããã£ãä»ããŠå¶åŸ¡ãããŸãã ãã ããã³ã³ããŒãã³ãããå€éšã«ããŒã¿ã転éããã«ã¯ã CustomEventsã䜿çšã§ããŸãã ãã®ã³ã³ããŒãã³ãã®å Žåãç¶æ
倿Žã€ãã³ãã远å ããŠããªãã¹ã³ããŠåå¿ã§ããããã«ããã®ãåççã§ãã ãããè¡ãã«ã¯ã2ã€ã®CustomEventãªããžã§ã¯ãã䜿çšããŠãã³ã³ã¹ãã©ã¯ã¿ãŒã«eventsããããã£ã远å ããŸãã
this.events = { "close": new CustomEvent("x-spoiler.changed", { bubbles: true, detail: {opened: false}, }), "open": new CustomEvent("x-spoiler.changed", { bubbles: true, detail: {opened: true}, }), };
ãŸãã openedã倿Žããããšãã«ã€ãã³ãããã£ã¹ããããããããã«attributeChangedCallbackç·šéãattributeChangedCallback ã
this.dispatchEvent(this.events[opened ? "open" : "close"]);
ããã§ãèå³ã®ããã€ãã³ããèããŠãã¹ãã€ã©ãŒã®ç¶æ
ã®å€åã«ã€ããŠç¥ãããšãã§ããŸãã
æ°ããã㢠ã
customElementsã«ã€ããŠããå°ã
èŠçŽ ãç»é²ãããšãã«ãã°ããŒãã«customElementsãªããžã§ã¯ãã®defineã¡ãœããã䜿çšããŸããã ããã«ã圌ã«ã¯ããã«2ã€ã®äŸ¿å©ãªæ¹æ³ããããŸãã
customElements.get(name)ã¯ãname name ïŒååšããå ŽåïŒãŸãã¯undefinedç»é²ããããŠãŒã¶ãŒèŠçŽ ã®ã³ã³ã¹ãã©ã¯ã¿ãŒãè¿ããŸãã
customElements.whenDefined(name)ã¯ãååãnameã®ã¢ã€ãã ãç»é²ãããå ŽåããŸãã¯ã¢ã€ãã ãæ¢ã«ç»é²ãããŠããå Žåã¯ããã«æåãããããã¹ãè¿ããŸãã ããã¯awaitã§ç¹ã«äŸ¿å©ã§ãããããã¯å¥ã®ãããã¯ã§ãã
ã«ã¹ã¿ã ã¢ã€ãã æ¡åŒµ
ãŠãŒã¶ãŒèŠçŽ ã¯ã©ã¹ããç¶æ¿ããŠãæ¢åã®ãã®ã«åºã¥ããŠæ°ãããŠãŒã¶ãŒèŠçŽ ãäœæã§ããŸãã ããšãã°ãã¹ãã€ã©ãŒãæ¡åŒµããå¿
èŠã«å¿ããŠããã€ãã®æ©èœã远å ã§ããŸãã å¿
èŠã«å¿ããŠã super.methodName()ãä»ããŠèŠªã¯ã©ã¹ã®åæ§ã®ã¡ãœãããåŒã³åºãããšãå¿ããªãããšãéèŠsuper.methodName()ã³ã³ã¹ãã©ã¯ã¿ãŒãšsuper()å Žåã¯å¿
èŠã§ãïŒã
æšæºèŠçŽ ã®æ¡åŒµ
仿§ã§ã¯ãæ¡åŒµæ©èœãšæšæºã®HTMLã¿ã°ãèš±å¯ãããŠããŸãã ããšãã°ãç¬èªã®ãã¿ã³å®è£
ãå¿
èŠã§ãããåæã«ããã©ãŠã¶ãã¿ã³ã®æ¢åã®æ©èœãããšãã°disabled ã tabindex ã typeãªã©ã®å±æ§ãdisabledãæ£ããæäœãä¿æããããšããå§ãããŸãã ãã ããå€ãã®æ©èœããããŸãã
ãŸããã¯ã©ã¹ã宣èšãããšããå¿
èŠãªã¿ã°ã®ã¯ã©ã¹ãå±éããå¿
èŠããããŸãã ãã¿ã³ã®å Žåãããã¯HTMLButtonElementã¯ã©ã¹ã«ãªããŸãã ã¯ã©ã¹ã®å®å
šãªãªã¹ãã¯ã仿§ã«èšèŒãããŠããŸã ã
2çªç®ã«ã3çªç®ã®ãã©ã¡ãŒã¿ãŒã§èŠçŽ ãç»é²ããå Žåãå±éããã¿ã°ã瀺ããªãã·ã§ã³ãªããžã§ã¯ããæž¡ãå¿
èŠããããŸãïŒåãã¯ã©ã¹ã¯è€æ°ã®ã¿ã°ã«å¯Ÿå¿ã§ããŸãïŒã
3çªç®ã«ããã®ãããªãŠãŒã¶ãŒèŠçŽ ã¯ãå±éããå¿
èŠãããéåžžã®ã¿ã°ãšããŠäœæãããŸãããis屿§ã¯ãŠãŒã¶ãŒèŠçŽ ã®ååãšåãã§ãã èŠçŽ ãdocument.createElementãä»ããŠäœæãããå Žåã2çªç®ã®åŒæ°ã®ããããã£ãšããŠæž¡ãããŸãã
次ã®ããã«ãªããŸãã
class FancyButton extends HTMLButtonElement { } customElements.define("fancy-button", FancyButton, {extends: "button"});
<button is="fancy-button" disabled>Fancy button!</button>
ç»é²åã®ã¢ã€ãã ã®ã¹ã¿ã€ãªã³ã°
ãã ãããŠãŒã¶ãŒãHTMLããŒã¯ã¢ãããååŸããJavaScriptã³ãŒããããŠã³ããŒãããŠå®è¡ããæ¹æ³ã«ã¯æéãããããŸãã DOMã§ã¬ã³ããªã³ã°ããããããŸã ç»é²ãããŠããããé©åã«åäœããªããŠãŒã¶ãŒå®çŸ©èŠçŽ ãäœããã®æ¹æ³ã§ã¹ã¿ã€ã«èšå®ããã«ã¯ã :definedç䌌:defined䜿çšã§ããŸãã æãç°¡åãªäœ¿çšäŸã¯ãæªç»é²ã®ãŠãŒã¶ãŒèŠçŽ ããã¹ãŠé衚瀺ã«ããããšã§ãã
*:not(:defined) { display: none; }
åèš
ã«ã¹ã¿ã èŠçŽ æè¡ã«åºã¥ããŠåå©çšå¯èœãªWebã³ã³ããŒãã³ããäœæããŸããã ãã ããå€ãã®æ¬ ç¹ããããŸãã ãããã£ãŠãããšãã°ãã¹ã¿ã€ã«ã®åé¢ã¯ãããŸããã section {display: block !important}ã«ãŒã«ã¯ãã³ã³ããŒãã³ãã®ããžãã¯ãç°¡åã«å£ããŠããŸããŸãã ãšã«ãããã¹ã¿ã€ã«ãJSã«çŽæ¥ã¶ãäžããã®ã¯æªãé³ã§ãã ã¹ãã€ã©ãŒã®ã³ã³ãã³ãã倿Žããããšãå°é£ã§ãinnerHTMLãinnerHTMLããŠæ°ããã³ã³ãã³ããã€ã³ã¹ããŒã«ãããšããã¿ã³ãã»ã¯ã·ã§ã³ãã¯ãªãã¯ãã³ãã©ãŒãæ¶ããŸãã ã³ã³ãã³ããå®éã«å€æŽããã«ã¯ãã³ã³ããŒãã³ãã®æ§é ãç¥ã£ãŠèæ
®ããå¿
èŠããããŸãã ãŸããããŒã¯ã¢ããã¯ã³ã³ã¹ãã©ã¯ã¿ãŒã«çŽæ¥ä¿åãããŸãã ããã¯æããã«ãåçŽãªåå©çšå¯èœãªã³ã³ããŒãã³ãã«å¿
èŠãªãã®ã§ã¯ãããŸããã ãããã®ãã¹ãŠã®æ¬ ç¹ãä¿®æ£ããããã«ãä»ã®ä»æ§ã䜿çšããŸãã
ã·ã£ããŠDOMïŒã·ã£ããŠDOMïŒ
ã·ã£ããŠDOMã®ä»æ§ã¯ãç°å¢ãšå
éšã³ã³ãã³ãããã¹ã¿ã€ã«ãšã¬ã€ã¢ãŠããåé¢ããåé¡ã解決ããŸãã
DOMã«ãã»ã«å
ç§ãã¡ã䜿çšããæšæºã®DOMã¢ãã«ã¯ãèŠçŽ ã®ãã¹ãŠã®åå«ãchildNodesãä»ããŠã¢ã¯ã»ã¹å¯èœã§ãããšä»®å®ãã querySelector()ãªã©ãä»ããŠquerySelector()ããšãã§ããŸãã DOM-ãã¹ã¹ã«ãŒãããã¹ãã®æ®µèœãã©ãã«ããå Žåã§ããåžžã«document.querySelectorAll("p")ä»ããŠæ€åºããdocument.querySelectorAll("p") ã ãã ããDOMããªãŒã«ãããã®ã§ã¯ãªããä»ã®ããŒã¯ã¢ããã衚瀺ããããšãå¯èœã§ãããããéåžžã®childNodeããã³querySelectorã«ãã£ãŠç¡èŠãããŸãã ãã®åäœã®æãåçŽãªäŸã¯ãå
éšã«è€æ°ã®<source>æã€<video>ã§ãã <source>ã®ã¿ãDOMã«è¿œå ãããšãç¬èªã®åé¢ããŒã¯ã¢ããïŒãããã¯ããã¿ã³ãªã©ïŒãåããæ¬æ Œçãªãããªãã¬ãŒã€ãŒã衚瀺ãããŸãã ç»é¢ã«è¡šç€ºããããã¹ãŠã®ãã®ã¯ãã·ã£ããŠDOMã«é
眮ãããŠããŸãã ã©ã®ããã«æ©èœããŸããïŒ
DOM attachShadow() . DOM- : Shadow DOM, Light DOM Flattened DOM. .
Light DOM â , DOM- : , innerHTML , childNodes querySelectorAll .
Shadow DOM â DOM-, shadowRoot . attachShadow shadowRoot , - innerHTML , appendChild DOM, this.shadowRoot .
Flattened DOM â Shadow DOM Light DOM. , . , Shadow DOM. Light DOM element.innerHTML , Shadow DOM element.shadowRoot.innerHTML , Flattened DOM . Flattened DOM Shadow DOM . , Light DOM . äŸïŒ
<x-demo>!</x-demo>
class Demo extends HTMLElement { constructor() { super(); this.attachShadow({mode: "open"}); this.shadowRoot.innerHTML = " ..."; } } customElements.define("x-demo", Demo);
DOM, .. «!». , , « ...».
: Shadow DOM , Shadow DOM . open . Shadow DOM shadowRoot .
. <slot> name Shadow DOM slot Light DOM. , Flattened DOM Lignt DOM. : ( 0, 1 ) slot - Light DOM <slot> name Shadow DOM. - <slot> , Shadow DOM. <slot> name , Light DOM slot .
, Shadow DOM Light DOM Shadow DOM <slot> , Light DOM <slot> .
: «» ( ) Shadow DOM, Light DOM <slot> . :
this.attachShadow({mode: "open"}); this.shadowRoot.innerHTML = ` <button type="button">${this.text["when-close"]}</button> <section style="display: none;"><slot></slot></section> `;
Shadow DOM, this.querySelector("button") this.shadowRoot.querySelector("button") . section .
, , textContent . . , , . .
: , «» DOM- Light DOM. , , : .
, Light DOM slot , <slot> name ( ). Light DOM slot , Shadow DOM <slot> , name ( ). slot - , <slot> ( ).
DOM Light DOM / Shadow DOM , .
. Shadow DOM <style> , Shadow DOM. ,
section { height: 50%; width: 50%; }
section , Shadow DOM. : section Shadow DOM . . , .
: :host . . , . , , .
, , , . Shadow DOM attributeChangedCallback . .
- . : :host-context(.red) , .red . , , .
Light DOM, . ::slotted , , - Light DOM. , . äŸïŒ
<name-badge> <h2>Eric Bidelman</h2> <span class="title"> Digital Jedi, <span class="company">Google</span> </span> </name-badge>
<style> ::slotted(h2) { margin: 0; font-weight: 300; color: red; } ::slotted(.title) { color: orange; } </style> <slot></slot>
, - , :host :host-context .
â :host . , :host . .
Shadow DOM CSS , , , , .
DOM
DOM DOM , . , DOM, , <video> .
DOM JavaScript- , DOM {mode: "open"} .
?
«» Shadow DOM, mode closed . Shadow DOM shadowRoot , null . shadowRoot attachShadow() , , shadowRoot - . Shadow DOM, .
<slot> slotchange , Light DOM, . , .
<slot> assignedNodes , DOM- Light DOM, . DOM- {flatten: true} , ( ).
Light DOM assignedSlot , , .
(HTML Templates)
, HTML.
Shadow DOM . - , innerHTML , - .
<template> , HTML Templates. , , . , DOM-, , <script> , <link> , , querySelector .
DOM- <template> content , DocumentFragment , . , appendChild .
, Shadow DOM: .
, «» . : , . , DOM-, . .
HTML- (HTML Imports)
. , , , , . HTML- : HTML-, (, , ) <link rel="import" href="x-spoiler.html"> .
, html- <template> <script> . , , <script> . html- , , : , , DOM , , document.getElementById . DOM- html- import link . <link> id, , import template , . <script> const ownerDocument = document.currentScript.ownerDocument , , , <template> ownerDocument , document . . !
, . , ( ), <link rel="import"> . . , , , .
ç·Žç¿ãã
. HTML- :
- « ». â .
app.html , , ? , 20 . , , , , . , . , , . - , . 100 , , n- . , , , .
- , HTTP/2. HTTP/2 , .
document.currentScript . , IE11 . , , id id, <template> , , , .- Firefox HTML- , . , - , Firefox, , .
, , . , . , HTML-. .
, IE , Edge 12 Safari 7- . .
v1 ( Chrome 54+ , Safari 10.1+ ) DOM v1 ( Chrome 53+ , Safari 10+ ). .
WebComponents/webcomponentsjs . , , webcomponents-sd-ce.js , DOM, HTML-.
, , : , â ShadyDOM â ShadyCSS DOM. . : <template> .
â Promise , CustomEvent , Object.assign() , Array.from() . - , webcomponents-platform es6-promise , polyfill.io .
Element.prototype.insertAdjacentHTML , . , - , issue . UPD: .
, , . ( ) .
WebReflection , ( Firefox). , , , .
, Babel , .
, :
,
. . :
- Internet Explorer 11+
- Edge 12+
- Firefox 35+
- Chrome 26+
- Safari 6.1+
- iOS- 8+
- Android browser 4.4+
:
- (HTML-),
<button is="fancy-button">button</button> . WebComponents . adoptedCallback .:defined , , .:host-context Safari, .- []
assignedNodes <slot> , . issue , .
, , . , .
â . Babel extends , Chrome , , ES5-. , custom-elements-es5-adapter.js , , . , . ES5-, - ( ), ( ).
DOM , :
<div id="custom-elements-adapter-test"> <script> (function() { if (isNative(window.customElements.define) === false) { </script> <script src="https://cdnjs.cloudflare.com/ajax/libs/webcomponentsjs/1.0.22/custom-elements-es5-adapter.js"></script> </div>
, â . â , . â , .
babel-plugin-transform-custom-element-classes . es5-adapter , IE11 , Reflect.construct . , , , . , , â . : , babel-polyfill . . , .
â babel-plugin-transform-builtin-classes WebReflection . , , IE11 - , . , WebComponents . â WebReflection, WebComponents . .
, , â Babel 7, . . , Chrome ( ), IE11, Reflect.construct .
: DOM ES5-, , . , â .
constructor : IE Safari HTMLUnknownElementConstructor , . .
.
DOM
, . -, ShadyCSS.prepareTemplate() , , â , . <template id="x-spoiler"> <x-spoiler> , ShadyCSS.prepareTemplate(document.getElementById("x-spoiler"), "x-spoiler") .
: ShadyCSS.styleElement(this) ;
:host() : :host(.zot) :host(.zot:not(.bar)) , :host(.zot:not(.bar:nth-child(2))) â .
::slotted : . , ::slotted(span) , .header ::slotted(span) .
.
â <template> . , DOMContentLoaded , , customElements.define() , DOM-, content template . : customElements.define() DOMContentLoaded , customElements.define() . . 次ã®ããã«ãªããŸãã
try { HTMLTemplateElement.bootstrap(document); } catch (e) { }
<template> DOM , : <template> DOM- . .
<script> : , <template> - : IE . . , - .
gulp
, , : html . <script> , . ( ) <template> , DOM HTML. <template> id , . DOM, <style> , CSS. , HTML , , <style> , css.
, , . ããã«ã¯æ¬¡ã®ãã®ãå¿
èŠã§ãã
templates.htmlPostCSSapp.jsBabel
gulp , , gulpfile , . github . :
src . html - (, ), scaffolding.js js- components -.
index.html @@templates , -, -, , es5- , app.js -, .
scaffolding.js , DOM ( ).
. : .
scripts <script> app.js :
gulp.task("scripts", () =>
templates , <template> :
gulp.task("templates", () =>
html- @@templates templates.html , templates . gulp, . , php include . gulp .
, , data -? Gulp . , , ShadyCSS.prepareTemplate() . , scaffolding.js :
document.querySelectorAll("template[data-component]").forEach(template => { ShadyCSS.prepareTemplate(template, template.dataset["component"]); });
以äžã§ãïŒ -, gulp . .
, . , , HTMLElement . x-component , , . ( , ):
$ $$ . querySelector querySelectorAll Light DOM. Chrome DevTools, jQuery .
fireEvent , . CustomEvent , , dispatchEvent . , c .
is localName , â . , , ( ).
getTemplateCopy - id .
makeShadowRoot DOM. , id ( this.is ) getTemplateCopy . DOM ( ShadyCSS.styleElement(this); ), . $ $$ shadowRoot .
. , properties , , / , ( ), . , :
, - .
- , .
, â , , ( ).
,
, , , - IE11, , ? Chrome, , es5- es5- -. .
, JS , - ( â ES), . , â . ? , . , , , 2018 75%. .
-, , ES5 ES6 . , , Babel scaffolding.js . :
gulp.task("scripts-es5", buildJS.bind(null, "es5")); gulp.task("scripts-es6", buildJS.bind(null, "es6")); function buildJS(mode) { return gulp.src("src/components/*.html") .pipe(concat(`app-${mode}.js`)) .pipe(insert.transform(content => { const document = (new JSDOM(content)).window.document; const scriptsTags = document.querySelectorAll("script"); const scriptsContents = Array.prototype.map.call(scriptsTags, tag => tag.textContent); return scriptsContents.join(""); })) .pipe(gulpif(mode === 'es5', gap.prependFile("src/scaffolding.js"))) .pipe(gulpif(mode === 'es5', babel({presets: ["env"]}))) .pipe(uglify()) .pipe(gulp.dest("dist")) }
, app-es5.js app-es6.js . , . , Ì , .
. , 150 ! . , , . , . . html:
(function () { var wcReady = ("attachShadow" in document.documentElement) && ('customElements' in window); var scripts; if (wcReady) { scripts = [ "./app-es6.js" ]; } else { scripts = [ "https://cdn.polyfill.io/v2/polyfill.js?features=default", "https://cdnjs.cloudflare.com/ajax/libs/webcomponentsjs/1.0.22/webcomponents-sd-ce.js", "https://cdn.jsdelivr.net/npm/template-mb@2.0.6/template.js", "./app-es5.js" ]; } scripts.forEach(function (script) { insertScript(script); }); function insertScript(src) { var script = document.createElement('script'); script.src = src; script.async = false; document.head.appendChild(script); } })();
. : , - bower es-5 . , , .
.
ããªããŒ
-, Polymer . , - - Polymer.Element . , -, .
, -, Polymer. - webcomponents.org Polymer, . , Polymer.
Polymer , , Polymer, , -. Polymer -, , , jQuery DOM JS.
Polymer HTML-.
Polymer, -, , .
Polymer API . , , , HTML- ( ES6 ), HTML- ( ). , , . , .
Polymer, . , , , Polymer.
, â , , . . . , ( , ) . , , PostCSS , . â IDE PostCSS- <style> . .
, node-sass . , <style></style> , .
çµè«
â , , , -. , - , - .
, (, ::part ::theme DOM ). - â , . - Polymer â , - Polymer, .
è³æº