web components


ここでいうWeb Componentsとは、shadow DOM、カスタム要素、HTMLテンプレートなど、DOMの動作を強化するためのツールのセットを指す.このブラウザAPIは特に混乱しています.
  • には統一された「Web Components」仕様はありません.各Webコンポーネントは異なる仕様で定義されています.
  • shadow DOMやカスタム要素などのWebコンポーネントでは、後方互換性のないバージョンの問題が発生しています.
  • ブラウザの実装は極めて不一致です.

  • これらの問題があるため、Webコンポーネントを使用するには、PolymerなどのWebコンポーネントライブラリを導入する必要があります.このライブラリは、ブラウザで欠落しているWebコンポーネントをシミュレートするスクリプトとして使用できます.
    HTMLテンプレート
    Webコンポーネント以前は、HTML解析に基づいてDOMサブツリーを構築し、必要に応じてこのサブツリーをレンダリングするメカニズムが欠けていた.1つの間接的なスキームはinnerHTMLを使用してタグ文字列をDOM要素に変換することであるが、この方法には深刻なセキュリティ上の危険性がある.もう1つの間接案はdcumentを用いる.createElement()は、各要素を構築し、単一のノード(DOMに追加するのではなく)に1つずつ追加しますが、タグには関係なく特に面倒です.逆に、ブラウザが自動的にDOMサブツリーに解析するが、レンダリングをスキップするように、ページに特殊なタグを事前に書きます.これはHTMLテンプレートの核心思想であり、ラベルはこの目的のために生まれたものである.
    1.DocumentFragmentの使用
    ブラウザでレンダリングする場合、上記の例のテキストはページにレンダリングされません.コンテンツはアクティブなドキュメントではないのでdocument.QuerySelector()などのDOMクエリメソッドではラベルは見つかりません.これは、HTMLテンプレートに含まれるDocumentFragmentノード内に存在するためです.ブラウザで開発者ツールを使用してWebページの内容を確認すると、次のDocumentFragmentが表示されます.

    このDocumentFragmentの参照は、要素のcontentプロパティで取得できます.
    console.log(document.querySelector('#foo').content); // #document-fragment

    このときのDocumentFragmentは、対応するサブツリーの最小化documentオブジェクトのようなものです.すなわち、DocumentFragmentのDOM照合メソッドは、サブツリーのノードを問い合わせることができます.
    const fragment = document.querySelector('#foo').content;
    console.log(document.querySelector('p')); // null
    console.log(fragment.querySelector('p')); // 

    ...


    DocumentFragmentも、HTMLに要素を一括して追加する効率的なツールです.たとえば、あるHTML要素に最も速い方法で複数のサブ要素を追加したいとします.documentを連続的に呼び出す場合.appendChild()は、手間がかかるだけでなく、複数回のレイアウトの再配置にもつながります.DocumentFragmentを使用すると、すべてのサブノードを一度に追加できます.レイアウトの再配置は最大1回のみです.//開始ステータス:

    // 期待的结果:

    //       document.createDocumentFragment()
    const fragment = new DocumentFragment();
    const foo = document.querySelector('#foo');
    //   DocumentFragment              
    fragment.appendChild(document.createElement('p'));
    fragment.appendChild(document.createElement('p'));
    fragment.appendChild(document.createElement('p'));
    console.log(fragment.children.length); // 3
    foo.appendChild(fragment);
    console.log(fragment.children.length); // 0
    console.log(document.body.innerHTML); //           

    2.templateラベルの使用
    前述の例では、DocumentFragmentのすべてのサブノードが効率的にfoo要素に移行し、移行後DocumentFragmentが空になったことに注意してください.同じ手順で、ラベルを使用して再現することもできます.
    const fooElement = document.querySelector('#foo');
    const barTemplate = document.querySelector('#bar');
    const barFragment = barTemplate.content;
    console.log(document.body.innerHTML);
    //     
    // 
    //
    // // DocumentFragment fooElement.appendChild(barFragment); console.log(document.body.innerHTML); // //
    // // // //
    //

    テンプレートをコピーする場合は、importNode()メソッドを使用してDocumentFragmentをクローンできます.
    const fooElement = document.querySelector('#foo');
    const barTemplate = document.querySelector('#bar');
    const barFragment = barTemplate.content;
    console.log(document.body.innerHTML);
    //     
    // 
    //
    // fooElement.appendChild(document.importNode(barFragment, true)); console.log(document.body.innerHTML); // //
    // // // //
    //

    3.テンプレートスクリプト
    スクリプトの実行は、DocumentFragmentのコンテンツを実際にDOMツリーに追加するまで延期できます.次の例では、このプロセスを示します.
    //    HTML:
    
    // 
    // const fooElement = document.querySelector('#foo'); const barTemplate = document.querySelector('#bar'); const barFragment = barTemplate.content; console.log('About to add template'); fooElement.appendChild(barFragment); console.log('Added template'); // // About to add template // Template script executed // Added template

    如果新添加的元素需要进行某些初始化,这种延迟执行是有用的。

    shadow DOM

    概念上讲,shadow DOM Web 组件相当直观,通过它可以将一个完整的 DOM 树作为节点添加到父 DOM 树。这样可以实现 DOM封装,意味着 CSS 样式和 CSS 选择符可以限制在影子 DOM子树而不是整个顶级 DOM 树中。
    shadow DOM 与 HTML 模板很相似,因为它们都是类似 document 的结构,并允许与顶级 DOM 有一定程度的分离。不过,shadow DOM 与 HTML 模板还是有区别的,主要表现在shadow DOM的内容会实际渲染到页面上,而 HTML 模板的内容不会。

    1. 理解shadow DOM

    假设有以下 HTML 标记,其中包含多个类似的 DOM 子树:

    Make me red!

    Make me blue!

    Make me green!


    この3つのDOMサブツリーは、テキストノードからそれぞれ異なる色にレンダリングされると推定されます.通常、各サブツリーに一意のスタイルを適用し、styleプロパティを使用しないには、各サブツリーに一意のクラス名を追加し、対応するセレクタでスタイルを追加する必要があります.

    Make me red!

    Make me green!

    Make me blue!


    もちろん、このスキームは、グローバルネーミング空間で変数を定義するのとあまり変わらないため、あまり理想的ではありません.これらのスタイルは他の場所とは無関係であることが知られているが、すべてのCSSスタイルはDOM全体に適用される.そのためには、これらのスタイルが他の場所に浸透しないように、CSSセレクタを十分に特別に保つ必要があります.しかし、これも折衷の方法にすぎない.理想的には、CSSを使用するDOMに制限することができるはずです.これはshadow DOMの最初の使用シーンです.
    2.shadow DOMの作成
    shadow DOMの競合を安全かつ回避することを考慮すると、すべての要素にshadow DOMが含まれるわけではありません.無効な要素またはすでにshadow DOMがある要素にshadow DOMを追加しようとすると、放出エラーが発生します.以下はshadow DOMを収容できる要素です.有効な名前で作成された任意のカスタム要素(HTML仕様の定義を参照)