Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Web Components, l'avenir des développeurs web

Julien Vey
November 08, 2013

Web Components, l'avenir des développeurs web

Templating, encapsulation, éléments customs, databinding... Tous les frameworks web modernes proposent actuellement leur propre solution.

Mais saviez-vous qu’une spécification du W3C proposant de standardiser tout ceci est en cours de rédaction ? Les Web Components.
Dans cette présentation, nous prendrons de l’avance ! Nous aborderons les concepts fondamentaux des Web Components : ShadowDOM, Mutation Observers, custom elements, Model-Driven-View, Object.observe()... mais aussi comment les utiliser dès aujourd'hui avec des frameworks tels que AngularJS ou Polymer

Julien Vey

November 08, 2013
Tweet

More Decks by Julien Vey

Other Decks in Programming

Transcript

  1. <a href="https://twitter.com/share" class="twitter-share-button" data- via="julienvey" data-lang="fr">Tweeter</a> <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/ ^http:/.test(d.location)?'http':'https';if(! d.getElementById(id))

    {js=d.createElement(s);js.id=id;js.src=p+':// platform.twitter.com/ widgets.js';fjs.parentNode.insertBefore(js,fjs );}}(document, 'script', 'twitter-wjs');</ script>
  2. mais Aujourd’hui c’est plutôt Ça ! utilisation de hidden ou

    display:none <div id="mytemplate" hidden> <img src="logo.png"> <div class="comment"></div> </div>
  3. ou encore Ça ! concaténation de String var html =

    ''; html += '<div>Hello<span>'; html += username; html += '</span></div>'; $('#monelement').insert(html);
  4. parsé mais PAS AFFICHÉ <script> ne s’EXÉCUTENT PAS <img> ne

    se CHARGENT PAS <template id="montemplate"> <img src=""> <div class="comment"></div> </template>
  5. et pour l’INSTANCIER ? le DOM est AFFICHÉ var t

    = document.querySelector('#montemplate'); t.content.querySelector('img').src = 'http://...'; document.body.appendChild(t.content.cloneNode(true));
  6. et pour l’INSTANCIER ? le DOM est AFFICHÉ <script> s’EXÉCUTENT

    var t = document.querySelector('#montemplate'); t.content.querySelector('img').src = 'http://...'; document.body.appendChild(t.content.cloneNode(true));
  7. et pour l’INSTANCIER ? le DOM est AFFICHÉ <script> s’EXÉCUTENT

    <img> se CHARGENT var t = document.querySelector('#montemplate'); t.content.querySelector('img').src = 'http://...'; document.body.appendChild(t.content.cloneNode(true));
  8. mais En fait... <video controls height="300" src="/ma/super/video"> #document-fragment <div> <div>

    <input type="button"> <input type="range" precision="float" max="596.48"> <div style="display:none;">0:00</div><div>9:56</div> <input type="button"> <input type="range" precision="float" max="596.48" style=""> <input type="button" style="display:none;"> <input type="button" style=""> </div> </video>
  9. Instancier du shadow DOM <div id="host"> </div> var host =

    document.querySelector('#host'); var shadow = host.createShadowRoot(); shadow.innerHTML = '<h2>Bouh ! Je suis le shadow DOM !</h2>';
  10. Instancier du shadow DOM <div id="host"> </div> var host =

    document.querySelector('#host'); var shadow = host.createShadowRoot(); shadow.innerHTML = '<h2>Bouh ! Je suis le shadow DOM !</h2>'; <div id="host"> #document-fragment <h2>Bouh ! Je suis le shadow DOM !</h2>; </div>
  11. Instancier du shadow DOM V2 <template id="montemplate"> ... </template> !

    <div id="host"> </div> <script> var shadow = document.querySelector('#host').createShadowRoot(); shadow.appendChild(document.querySelector('#montemplate').content); </script>
  12. shadow DOM <div>Je commence à apprendre les Web Components</div> <content></content>

    <div>J’ai fini d’apprendre les Web Components</div>
  13. shadow DOM host <div>Je commence à apprendre les Web Components</div>

    <content></content> <div>J’ai fini d’apprendre les Web Components</div> <div id="host"> <div>Hello World !</div> </div>
  14. shadow DOM host résultat <div>Je commence à apprendre les Web

    Components</div> <content></content> <div>J’ai fini d’apprendre les Web Components</div> <div id="host"> <div>Hello World !</div> </div> <div id="host"> #document-fragment <div>Je commence à apprendre les Web Components</div> <div>Hello World !</div> <div>J’ai fini d’apprendre les Web Components</div> </div>
  15. shadow DOM <hgroup> <content select="h2"></content> <div>Bouh ! Je suis le

    shadow DOMMMM !</div> <content select="h1:first-child"></content> </hgroup> <content select="*"></content> <div id="host"> <h1>Titre</h1> <h2>Sous-titre</h2> <div>contenu</div> </div> host
  16. résultat <div id="host"> #document-fragment <hgroup> <h2>Sous-titre</h2> <div>Bouh ! Je suis

    le shadow DOMMMM !</div> <h1>Titre</h1> </hgroup> <div>contenu</div> </div>
  17. <h1>Bienvenue</h1> <div id="webcomponents"> #document-fragment <h1>Les Web Components c’est ça :</h1>

    <div>Templates</div> <div>Shadow DOM</div> <div>DOM Observe</div> <div>Object.observe()</div> <div>Custom elements</div> <h1>Et c’est génial</h1> </div>
  18. <h1>Bienvenue</h1> <div id="webcomponents"> #document-fragment <style>h1 { color : red }</style>

    <h1>Les Web Components c’est ça :</h1> <div>Templates</div> <div>Shadow DOM</div> <div>DOM Observe</div> <div>Object.observe()</div> <div>Custom elements</div> <h1>Et c’est génial</h1> </div>
  19. <h1>Bienvenue</h1> <div id="webcomponents"> #document-fragment <style>h1 { color : red }</style>

    <h1>Les Web Components c’est ça :</h1> <div>Templates</div> <div>Shadow DOM</div> <div>DOM Observe</div> <div>Object.observe()</div> <div>Custom elements</div> <h1>Et c’est génial</h1> </div>
  20. <h1>Bienvenue</h1> <div id="webcomponents"> #document-fragment <style>h1 { color : red }</style>

    <h1>Les Web Components c’est ça :</h1> <div>Templates</div> <div>Shadow DOM</div> <div>DOM Observe</div> <div>Object.observe()</div> <div>Custom elements</div> <h1>Et c’est génial</h1> </div>
  21. et pour Styler l’élément host ? <style> @host { /*

    Le style de l'élément host */ } </style>
  22. <element name="megabutton" constructor="MegaButton"> <template> <style>...</style> <content></content> </template> <script> MegaButton.prototype =

    { doSomething: function() {…} }; </script> </element> <link rel="component" href="megabutton.html"> !
  23. <element name="megabutton" constructor="MegaButton"> <template> <style>...</style> <content></content> </template> <script> MegaButton.prototype =

    { doSomething: function() {…} }; </script> </element> <link rel="component" href="megabutton.html"> ! <megabutton>Mega Button?</megabutton> !
  24. <element name="megabutton" constructor="MegaButton"> <template> <style>...</style> <content></content> </template> <script> MegaButton.prototype =

    { doSomething: function() {…} }; </script> </element> <link rel="component" href="megabutton.html"> ! <megabutton>Mega Button?</megabutton> ! <script> var button = new MegaButton(); … </script>
  25. Cycle de vie des Custom Elements <element extends="time" name="x-clock"> <script>

    // … this.lifecycle({ inserted: function() { this.startUpdatingClock(); }, removed: function() { this.stopUpdatingClock(); } }); // … </script> </element>
  26. Mutation observers var observer = new MutationObserver(function(mutations, observer) { mutations.forEach(function(record)

    { for (var i = 0, node; node = record.addedNodes[i]; i++) { console.log(node); } }); });
  27. Mutation observers var observer = new MutationObserver(function(mutations, observer) { mutations.forEach(function(record)

    { for (var i = 0, node; node = record.addedNodes[i]; i++) { console.log(node); } }); }); observer.observe(el);
  28. Mutation Observer vs Mutation Event var observer = new MutationObserver(function(mutations,

    observer) { mutations.forEach(function(record) { for (var i = 0, node; node = record.addedNodes[i]; i++) { console.log(node); } }); }).observe(document, {childList: true}); document.addEventListener('DOMNodeInserted', function(e) { console.log(e.target); }, false);
  29. Object.Observe() function observeChanges(changes) { console.log('Callback changement'); changes.forEach(function(change) { console.log('Ce qui

    a changé', change.name); console.log('La nature du changement', change.type); console.log('L''ancienne valeur', change.oldValue ); console.log('La nouvelle valeur', change.object[change.name]); }); }
  30. Object.Observe() function observeChanges(changes) { console.log('Callback changement'); changes.forEach(function(change) { console.log('Ce qui

    a changé', change.name); console.log('La nature du changement', change.type); console.log('L''ancienne valeur', change.oldValue ); console.log('La nouvelle valeur', change.object[change.name]); }); } var o = {}; Object.observe(o, observeChanges);
  31. Model-Driven-View <html> <head> <script> var maValeur = "World !"; </script>

    </head> <body> <div> <h1>Hello {{maValeur}}</h1> </div> </body> </html>
  32. AngularJS La Philosophie WEB COMPONENTS DÉCLARATIF plutôt qu’IMPÉRATIF Une EXTENSION

    du LANGAGE HTML DIRECTIVES AngularJS == Web Components CUSTOM ELEMENTS
  33. AngularJS La Philosophie WEB COMPONENTS <tabs> <tab title="Onglet 1"> Hello

    Section 1! </tab> <tab title="Onglet 2"> Hello Section 2! </tab> </tabs> <tabs ng-app="tabs"> <pane title="Onglet 1"> Hello Section 1! </pane> <pane title="Onglet 2"> Hello Section 2! </pane> </tabs> Custom Element Directive angular
  34. Polymer Project <polymer-element name="tk-element-proto"> <template> <span>I'm <b>tk-element-proto</b> with a prototype.</span>

    </template> <script> Polymer('tk-element-proto', { ready: function() { //... } }); </script> </polymer-element> + Gestion du cycle de vie + Databinding
  35. Polymer.Dart <polymer-element name="click-counter"> <template> <button on-click="{{increment}}">Click Me</button> <p>You clicked the

    button {{count}} times.</p> </template> <script type="application/dart" src="click_counter.dart"></script> </polymer-element> import 'package:polymer/polymer.dart'; import 'dart:html'; ! @CustomTag('click-counter') class ClickCounterElement extends PolymerElement { @observable int count = 0; ClickCounterElement.created() : super.created(); ! void increment(Event e, var detail, Node target) { count += 1; } }