ããã«ã¡ã¯ ããã³ããšã³ãéçºã§ã¯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.html
PostCSS
app.js
Babel
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, .
è³æº