Web Componentsのはなし

Asaka

Web Componentsって?

ちゃんとした話は↓見てください 発表した人の資料とブログ: HTML5とか勉強会でWeb ComponentsとPolymerについて話してきた

Web Components

  • HTML+CSS+JSの部品を新たな要素として再定義する
    • ex) Google Mapの埋め込み、Twitterボタン

  • UIである必要はなく、機能の抽象化も可能
    • ex) Desktop Notification

  • スコープが存在し、外部に干渉しない
    • ex) CSSのid, class名

  • 将来、Webの標準になる予定

Web Componentsを構成する4つの要素

  • Custom Elements
  • Templates
  • HTML Imports
  • Shadow DOM

Custom Elements

  • 開発側で独自のエレメントを作成できる
  • エレメント名には"-"を含める必要がある
  • ↓みたいな感じでjsで登録する
  • 
        var XElementPrototype = Object.create(HTMLElement.prototype);
        var XElement = document.registerElement('x-element', {
          prototype: XElementPrototype
        });
              

Custom Elements

エレメント生成時、ノードへのアタッチ/削除時、属性変更時のコールバックを設定できる

  • createdCallback
  • attachedCallback
  • detachedCallback
  • attributeChangedCallback

      var XElementPrototype = Object.create(HTMLElement.prototype);
      // 生成時に呼ばれるコールバック
      XElementPrototype.createdCallback = function(){
        console.log("created");
      };
      var XElement = document.registerElement('x-element', {
        prototype: XElementProtype
      });

      new XElement() // => "created"
              

Templates

描画されない不活性なテンプレート要素

  • DOMとして取得して扱うことができる
  • パースされても描画されない
  • クローンして追加されるまでは実行されない

      
          

Shadow DOM

HTMLElementとHTML+CSS+JSの間にShadowRootっていうやつを挟んでやると、影響をそのエレメント内に閉じることができる


              +-> HTMLElement -> (HTML+CSS+JS)
    Document -|
              +-> HTMLElement -> ShadowRoot -> (HTML+CSS+JS)
          


      var template = document.querySelector('#tmpl');
      var div = document.querySelector('div');

      var clone = document.importNode(template.content, true);
      var shadowRoot = div.createShadowRoot();

      shadowRoot.appendChild(clone);
          

HTML Import

  • JavaScriptやCSSを1リソースでロード可能
  • 依存関係が明確になる
  • インポート先の<script>は描画をブロックしない
  • async属性を付与可能

      <html>
        <head>
          <title>x-element</title>
          <link rel='import' href='x-element.html'>
        </head>
        <body>
          <x-element></x-element>
        </body>
      </html>
            

この4つの要素をどう使う

TemplateでCustom Elementの要素を作って、Shadow DOMで閉じてコンポーネント化し、importして使う


<!-- index.html -->
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>WebComponentsSample</title>
    <link rel='import' href='x-element.html'>
</head>
<body>
  <x-element></x-element>
</body>
</html>


<!-- x-element.html -->
<template id='tmpl'>
    <style>
        input, button {
          border:1px solid #000;
          border-radius: 3px;
        }
    </style>
    <input type='text'>
    <button>Button</button>
</template>
<script>
        
    // importされるとdocumentはimport元のdocumentになるため自身のドキュメントを取得する
    var importDoc = document.currentScript.ownerDocument;

    var XElementPrototype = Object.create(HTMLElement.prototype);
    XElementPrototype.createdCallback = function(){
        console.log("created");

        var template = importDoc.querySelector('#tmpl');

        var clone = importDoc.importNode(template.content, true);

        // x-elementのshadowRootを生成する
        var shadowRoot = this.createShadowRoot();

        shadowRoot.appendChild(clone);

    };
    var XElement = document.registerElement('x-element', {
      prototype: XElementPrototype
    });
</script>
          

Web Components

自分でコンポーネント作るのちょっと面倒...

Polymer

  • 未実装のブラウザでも動くようにがんばってくれる
  • Web-Componentsのコンポーネントを簡単に作れる
  • それ以外にもWebでMaterial Designとか色々あるっぽい
  • WebComponentsのhelper + αみたいな感じ?
  • Polymer Designer(GUIでPolymerのコードを作れる)

      <link rel="import" href="bower_components/polymer/polymer.html">

      <polymer-element name="x-element" noscript>
        <template>
            <style>
                input, button {
                  border:1px solid #000;
                  border-radius: 3px;
                }
            </style>
            <input type='text'>
            <button>Button</button>
        </template>
      </polymer-element>
                

実際にやってみる

(ここから黒い画面が続きます。)

でも

標準で動作する主要ブラウザは今のところchromeとopearaだけっぽい (polyfill使えばなんとか動くっぽいけど)

なので、

まだはやい!

おわり