Web Components

Grégory Paul, Valtech

Web Components

Grégory Paul - http://paulgreg.me/ - @paulgreg

Web Component ?

Web Component

Web Component

démo live

Sommaire

Custom Elements

Custom Elements

Création

var XFoo = document.registerElement('x-foo');

démo

Custom Elements

Argument facultatif

            var XFoo = document.registerElement('x-foo', {
                prototype: Object.create(HTMLElement.prototype)
            });
            document.body.appendChild(new XFoo());
        

démo

Parenthèse : ECMAscript 5

Custom Elements

Avec des propriétés et méthodes

            var XFoo = document.registerElement('x-foo', {
              prototype: Object.create(HTMLElement.prototype, {
                bar: {
                  get: function() { return 5; }
                },
                foo: {
                  value: function() {
                    alert('foo() called');
                  }
                }
              })
            });
        

démo

Custom Elements

Surcharge

            var MegaButton = document.registerElement('mega-button', {
              prototype: Object.create(HTMLButtonElement.prototype),
              extends: 'button'
            });
            var megabtn = document.createElement('button', 'mega-button');
            megabtn.innerText = "Mega button";
            document.body.appendChild(megabtn);
        

démo

Custom Elements

Depuis l’inspecteur

Custom Elements

Cycle de vie

nom du callback appelé quand
createdCallback une instance est créée
attachedCallback une instance est attachée au DOM
detachedCallback une instance est supprimée du DOM
attributeChangedCallback
(name, oldVal, newVal)
un attribut est ajouté, modifié ou supprimé

Custom Elements

Cycle de vie : exemple

            var proto = Object.create(HTMLElement.prototype);
            proto.createdCallback = alert.bind(window, 'instance créée');
            proto.attachedCallback = alert.bind(window, 'attachée au DOM');
            var XFoo = document.registerElement('x-foo', {
                prototype: proto
            });
            var xfoo = new XFoo();
            document.body.appendChild(xfoo);
        

démo

Custom Elements

Initialisation de l’élément

            var proto = Object.create(HTMLElement.prototype);
            proto.createdCallback = function() {
               this.innerHTML = 'Je suis x-foo !';
            };
            var XFoo = document.registerElement('x-foo', {
                prototype: proto
            });
            var xfoo = new XFoo();
            document.body.appendChild(xfoo);
        

démo

Custom Elements

Depuis l’inspecteur

Templates

Templates

Templates tel que vous y êtes sûrement habitué...

            <div id="mytemplate" class="hidden">
              <strong></strong><br>
              <img src="http://upload.wikimedia.org/wikipedia/meta/0/08/Wikipedia-logo-v2_1x.png">
            </div>
        

Templates

Templates tel que vous y êtes sûrement habitué...

            <script id="mytemplate" type="text/x-handlebars-template">
              <strong></strong><br>
              <img src="http://upload.wikimedia.org/wikipedia/meta/0/08/Wikipedia-logo-v2_1x.png">
            </script>
        

Templates

De «vrais» <template>

            <template id="mytemplate">
              <strong></strong><br>
              <img src="http://upload.wikimedia.org/wikipedia/meta/0/08/Wikipedia-logo-v2_1x.png">
            </template>
        
Parsé (DOM) mais pas rendu (<script> pas lancé, <img> pas chargées, etc)

démo

Parenthèse : DocumentFragment

createDocumentFragment

            var docfrag = document.createDocumentFragment();
            ["IE", "FF", "Chrome"].forEach(function(browser) {
              var li = document.createElement("li");
              li.textContent = browser;
              docfrag.appendChild(li);
            });
            var ul = document.createElement("ul");
            ul.appendChild(docfrag);
            document.body.appendChild(ul);
        

660 ops/s vs 15,414 ops/s (jQuery vs documentFragment)

démo

Shadow DOM ?

Shadow DOM

démo <video> <input>
Sous Chrome, activez “Show Shadow DOM” dans les préférences de la console développeur.
(F12 > > General > Elements)

Shadow DOM

Shadow DOM

Depuis une balise <article>

            <article />
        

démo

Shadow DOM

Shadow DOM

Depuis une balise <article>

            <article>Hello, world!</article>
        

démo

Shadow DOM

Points d’insertion 1/2

            <article>
            <span>Grégory</span>
            </article>
        

Shadow DOM

Points d’insertion 2/2

            var root = document.querySelector('article').createShadowRoot();
            root.appendChild(document.querySelector('template').content);
        

Résultat

démo

Shadow DOM

Points d’insertion via sélecteurs 1/2

            <article>
            <span class="firstname">Grégory</span>
            <span class="company">Valtech</span>
            </article>
        

Shadow DOM

Points d’insertion via sélecteurs 2/2

            var root = document.querySelector('article').createShadowRoot();
            root.appendChild(document.querySelector('template').content);
        

Résultat

démo

Shadow DOM / Styles

            <h3>Hello</h3>
        

Surcharge du style d’un deuxième <h3>

            var h3 = document.createElement('h3');
            document.body.appendChild(h3);
            var root = h3.createShadowRoot();
            root.innerHTML = '<style>h3 { color: red; }</style>' +
                             '<h3>Shadow DOM</h3>';
        

Les styles ne sortent pas du "shadow root"

démo

Shadow DOM / Styles

            <button>Hello World</button>
        

:host

            var button = document.querySelector('button');
            var root = button.createShadowRoot();
            root.innerHTML = '<style>'+ 
                ':host { text-transform: uppercase; }' +
                ':host(:hover) { font-weight: bold; }' +
                '</style>' + 
                '<content></content>';
        

host permet de styler le noeud

démo

Shadow DOM / Styles

            <p class="main">
              <button>Hello World</button>
            </p>
        

:host-context

            var button = document.querySelector('button');
            var root = button.createShadowRoot();
            root.innerHTML = '<style>'+ 
                ':host-context(.main) { text-transform: uppercase; }' +
                '</style>' + 
                '<content></content>';
        

host-context s’applique à tous les noeuds parents

démo

Shadow DOM / Styles

            <p>
              <button>Hello World</button>
            </p>
        

:host-context

            var button = document.querySelector('button');
            var root = button.createShadowRoot();
            root.innerHTML = '<style>'+ 
                ':host-context(.main) { text-transform: uppercase; }' +
                '</style>' + 
                '<content></content>';
        

Ne fonctionne pas car le parent ne contient pas la classe main

démo

Shadow DOM / Styles

            <button><span>Hello </span></button>
        
            var button = document.querySelector('button');
            var root = button.createShadowRoot();
            root.innerHTML = '<content></content><span>Shadow DOM<span>';
        

démo

Shadow DOM / Styles

Résultat

Le CSS ne s’applique que dans le shadow DOM

Shadow DOM

            <button></button>
        

::shadow fonctionne également pour querySelector

            var button = document.querySelector('button');
            var root = button.createShadowRoot();
            root.innerHTML = '<span>Shadow DOM<span>';
            var span = document.querySelector('button::shadow span');
            span.textContent
        

démo

HTML imports ?

HTML imports

Utilisation

            <head>
            <link rel="import" href="/elements/x-foo.html">
            </head>
        

Démo

Web Component Mappy

Support ?

Support

Templates
HTML Imports
Custom Elements
Shadow DOM

https://jonrimmer.github.io/are-we-componentized-yet/

Polymer, X-Tags, Bosonic

Ces librairies proposent :

Support via ces librairies

Templates
HTML Imports
Custom Elements
Shadow DOM

enfin, en théorie...

Polymer ?

Polymer

Démos : <mappy-element>, <x-video>

X-Tags ?

X-Tags

Démos : <mappy-element>, <x-mario>

Bosonic ?

Bosonic

Démos et sources (<mappy-element>)

Références

Références

Conclusion

Conclusion

Questions / Réponses

Resources

Resources