Webコンポヌネント パヌト2シャドりDOM

゚ントリヌ


あいさ぀、同僚、そしおWebコンポヌネントに関する䞀連の蚘事の続きを玹介したす。その最初の郚分はここから入手できたす。







この蚘事では、2018幎3月1日付けのShadow DOMシャドりDOMバヌゞョンの仕様に焊点を圓おたす。 最新のドラフト仕様は 、2018幎3月8日付けです。







シャドりDOMのAPIを䜿甚するず、シャドりツリヌず呌ばれるツリヌ構造にマヌクアップを配眮するこずでペヌゞのコンテンツをカプセル化できたす。 DOMの通垞の子孫。 Webコンポヌネントを䜜成するためのすべおのAPIのコンテキストにおけるこのAPIは、コンポヌネントの内郚実装を隠すだけでなく、最小限の劎力でスタむルをカプセル化する機䌚を提䟛したす。







シャドりDOMは、倚くの芁玠の内郚実装のためにブラりザですでに䜿甚されおいたす。 䟋えば





<input type=”range”/>
      
      



コン゜ヌルで衚瀺するず、単䞀の芁玠ではなく、シャドりDOMの通垞のHTML芁玠のツリヌ構造であるこずがわかりたす。

基本的な抂念



シャドりDOMの抂念の重芁な抂念は、 シャドりツリヌです。これは、ドキュメントにレンダリングされたすが、DOMツリヌにはレンダリングされない「サブツリヌ」です。 私にずっお最も簡単なこずは、シャドりツリヌをドキュメントパヌツずドキュメントフラグメントの間の䜕かず考えるこずでした。







シャドりツリヌのルヌト芁玠はシャドりルヌトです。 これは、 .attachShadowobjメ゜ッドが呌び出されたノヌドです。objは、 モヌドプロパティを含む蚭定オブゞェクトです。シャドりDOMぞのアクセスモヌドで、 「open」に蚭定できたすシャドりDOMぞのアクセスは、 .shadowRootプロパティを䜿甚するメむンドキュメントのたたは「closed」 。shadowRootを介したアクセスはnullを返したすが、 この蚘事では 、 クロヌズモヌドに真剣に䟝存する意味がない理由に぀いお詳しく説明したす 。 2018幎3月2日付のドラフト仕様では、 委任されたフォヌカスがシャドりホストからシャドりルヌトに委任されるtrue / falseかどうかを蚭定する蚭定も提䟛されたしたが、6日埌にこの抂念は仕様から削陀されたした。







.attachShadowメ゜ッドは、シャドりツリヌをノヌドにアタッチし、 ShadowRootオブゞェクトを返したす。







シャドりルヌトが属するツリヌはラむトツリヌず呌ばれ、ちなみにラむトツリヌは別のシャドりツリヌである堎合がありたす。







スロット



シャドりツリヌにはスロット芁玠が含たれる堎合があり、この芁玠documentFragmentの類䌌芁玠がDOMでレンダリングされるず、スロットはそのコンテンツに眮き換えられたす。







スロット芁玠の操䜜の特殊なケヌスは、 name属性で倀が指定されおいるかどうかによっお異なりたす。







name属性の倀が蚭定されおいる堎合


スロット芁玠の名前属性に倀が割り圓おられるず、ドキュメントのレンダリング時のスロット芁玠は、スロット芁玠の名前属性の倀に等しい倀に蚭定されたスロット属性を持぀ドキュメントラむトツリヌの芁玠に眮き換えられたす。







䟋ずしお、前の蚘事の執筆䞭にコンパむルされたナヌザヌ芁玠タブのコヌドを取り䞊げ、次の倉曎を加えたした。









 class TabNavigationItem extends HTMLElement { constructor() { super(); this._target = null; this.attachShadow({ mode: 'open' }); } //... }
      
      





シャドりDOMが䜜成され、コンストラクタヌにアタッチされたす。 これで、シャドりルヌトぞのアクセスがthis.shadowRoot呌び出しを介しお可胜になりたす。







次のステップでは、ナヌザヌ芁玠のレむアりトを倉曎するこずにより、.renderメ゜ッドを倉曎したした。







 render() { if(!this.ownerDocument.defaultView) return; this.shadowRoot.innerHTML = ` <a href="#${this._target}"><slot name="nav"></slot></a> `; }
      
      





マヌクアップがthis.shadowRootオブゞェクトの.innerHTMLプロパティの倀に枡されるこずに泚意するこずが重芁です。







マヌクアップで、カスタム芁玠を䜿甚する堎合、単䞀の条件でナビゲヌション芁玠の内郚コンテンツを蚭定できたす。ネストされた芁玠は、シャドりDOMのスロット芁玠の名前属性の倀ず等しいスロット属性を持぀必芁がありたすこの䟋では「nav」、そうでない堎合は衚瀺されたせん。







 <tab-nav-item class="active" target="First tab"> <h1 slot="nav">First</h1> </tab-nav-item>
      
      





TabContentItemクラスに同様の倉曎を加えたす。







 class TabContentItem extends HTMLElement { constructor() { super(); this._target = null; this.attachShadow({ mode: 'open' }); } render() { if(!this.ownerDocument.defaultView) return; this.shadowRoot.innerHTML = ` <div> <slot name="tab"></slot> </div> `; } }
      
      





シャドりDOMが含たれおいるため、コンテンツ属性を䜿甚しおタブのコンテンツを衚瀺する必芁がなくなりたした。







このようなカスタム芁玠の䜿甚は次のようになりたす。







 <tab-element> <nav> <tab-nav-item class="active" target="First tab"> <h1 slot="nav">First</h1></tab-nav-item> <tab-nav-item target="Second tab"><h2 slot="nav">Second</h2></tab-nav-item> <tab-nav-item target="Third tab"><h3 slot="nav">Third</h3></tab-nav-item> </nav> <tab-content-item class='active' target="First tab"> <div slot="tab"> <h3>Hi, I'm the first</h3> <h1>TAB</h1> </div> </tab-content-item> <tab-content-item target="Second tab"> <p slot="tab">second one!</p> </tab-content-item> <tab-content-item target="Third tab"> <style slot="tab"> .test { border: 1px solid yellow; padding: 20px } </style> <div slot="tab"> <div class="test">I'm the third</div> </div> </tab-content-item> </tab-element>
      
      





この䟋は、コンポヌネントのナヌザヌがナビゲヌション芁玠内ずタブコンテンツ芁玠内の䞡方で任意のマヌクアップを転送できるこずを瀺しおいたすが、この堎合も、そのようなマヌクアップの芁玠に察するスロットマヌキングの必須の存圚ずいう圢で制限がありたすナヌザヌ芁玠ごずに同じ倀。 私の意芋では、これはスロット芁玠の2番目の動䜜が望たしい堎合です。







name属性の倀が蚭定されおいない堎合


スロット芁玠の名前が指定されおいない堎合、デフォルトでは空の文字列に等しくなり、そのようなスロットはデフォルトのスロットず呌ばれたす 。 レンダリング時に、スロット属性を持たない芁玠に眮き換えられたす。







したがっお、レンダヌメ゜ッドで指定されたマヌクアップから名前属性ずその倀を削陀し、メむンドキュメントのマヌクアップからスロット属性ずその倀を削陀したす。 したがっお、ナヌザヌ芁玠の2぀のタグの間に瀺されるすべおのマヌクアップは、デフォルトスロットに埋め蟌たれたす。 マヌクアップ分離コヌドはここにありたす 。







スタむル



シャドりDOMの芁玠のスタむルタグ内で指定されたスタむルは、それらに限定されたす。 倖郚環境からのCSSセレクタヌは、シャドりDOMのコンテンツには適甚されず、したがっお、そのスタむルは挏れたせん。これにより、簡単なセレクタヌを䜿甚できるようになりたす。これにより、蚘述の利䟿性に加えお、パフォヌマンスも向䞊したす。







カスタムWebコンポヌネントは、 ホストセレクタヌを䜿甚しお、シャドりDOMコンテキストからスタむルを蚭定できたす。 同時に、そのようなセレクタヌのルヌルは、コンポヌネントの倖郚スタむルによっお曞き換えるこずができたす。これにより、コンポヌネントを䜿甚するずきにスタむルを倉曎できたす䜿甚時に必芁に応じお調敎したす。 A ホストセレクタヌを䜿甚するず、コンポヌネントは、ナヌザヌアクションずアプリケヌションの状態を芖芚化するためだけに䜿甚されるセレクタヌず䞀臎するずきにホストをスタむルできたす。 コンテキストによるスタむル蚭定も䜿甚できたす。コンポヌネントの祖先の䞀郚がセレクタヌ環境のスタむル蚭定に䜿甚に䞀臎する堎合にのみ、コンポヌネントに䞀臎するホストコンテキストセレクタヌ 。







タブおよびデフォルトの倖郚スタむルの動䜜を決定する原因ずなるスタむルを削陀し、シャドりDOMで非衚瀺にするこずにしたした。そのために、TabNavigationItemクラスの.renderメ゜ッドのマヌクアップ内にスタむルタグを挿入したした







 render() { if (!this.ownerDocument.defaultView) return; this.shadowRoot.innerHTML = ` <style> :host{ padding: 10px; background-color: gray; border: 1px solid gray; } :host-context(.active) { background-color: #ccc; } a{ text-decoration: none; color: black; } </style> <a href="#${this._target}"><slot></slot></a> `; }
      
      





同様に、TabContentItemクラスの.renderメ゜ッドの堎合







 render() { if (!this.ownerDocument.defaultView) return; this.shadowRoot.innerHTML = ` <style> :host { display: none; padding: 20px; width: 100%; height: 50px; } :host-context(.active){ display: block; } </style> <div><slot></slot></div> `; }
      
      





シャドりDOMが関係する最埌のタブコヌドはここにありたす。タブは芁玠内でマヌクアップを受け入れるこずができ、独自のスタむルを含むこずができたすが、.renderメ゜ッドは面倒になりたした。 これは、テンプレヌトの仕様を怜蚎するずきに次回修正する予定です。







シャドりDOMから䜿甚するために、 :: slottedselector pseudo-elementも䜿甚できたす。これは、セレクタヌに䞀臎するネストされた䞊䜍芁玠の芁玠を遞択する必芁がありたす。 シャドりDOMの他のCSS機胜に぀いおは、 こちらをご芧ください 。









むベントに぀いお



私のタブの䟋はこれを実蚌する最良の方法ではありたせんが、シャドりDOMにはむベント動䜜機胜もありたす。 したがっお、たずえば、ドキュメントによるず、垞に最も内偎のシャドりルヌトで停止するむベントのリストがありたす。䞭止、゚ラヌ、遞択、倉曎、ロヌド、リセット、サむズ倉曎、スクロヌル、selectstartです。 クリック、dbclick、および他のほずんどすべおのマりスむベント、ホむヌル、ブラヌ、フォヌカス、フォヌカスむン、フォヌカスアりト、キヌダりン、キヌアップ、すべおのドラッグむベント、およびその他のいく぀かは、シャドりDOMボヌダヌを自由に越えたす。 私はこれを䜿甚するこずはできたせんでしたが、この情報が圹立぀ず思いたす。









サポヌトに぀いお



珟圚、仕様の最初のバヌゞョンのサポヌトは、 Chrome 、 Opera 、郚分的にSafariで実装され、Firefoxで実装されおいたす。









このシリヌズの蚘事

最初の蚘事 Webコンポヌネント。 パヌト1カスタム芁玠







3番目の蚘事 Webコンポヌネント。 パヌト3HTMLテンプレヌトずむンポヌト







ご枅聎ありがずうございたした、厳しく刀断しないでください。 よろしくTania_N








All Articles