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

Web Components, l'avenir des développeurs web

33f4da946e4712d9aac7ea915fdc71e4?s=47 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

33f4da946e4712d9aac7ea915fdc71e4?s=128

Julien Vey

November 08, 2013
Tweet

More Decks by Julien Vey

Other Decks in Programming

Transcript

  1. WEB COMPONENTS L’avenir des développeurs WEB

  2. Julien Vey Numergy @julienvey julienvey.com ! ! !

  3. Reinventer la Roue

  4. Reinventer la Roue mais cette fois on fait les choses

    bien !
  5. Un STANDARD du En cours de redaction W3C

  6. <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>
  7. <tweet user="julienvey" />

  8. <megabutton>Mega Button?</megabutton>

  9. <rating max="5" />

  10. <tabs> <tab title="Active Tab">...</tab> <tab title="Inactive Tab">...</tab> <tabs>

  11. Templates Séparer le FOND de la FORME

  12. Un Template c’est quoi ? GABARIT MODÈLE Patron Layout

  13. 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>
  14. ou Ça ! utilisation de <script> <script type="text/x-handlebars-template" id="monTemplate"> <img

    src="logo.png"> <div class="comment"></div> </script>
  15. ou encore Ça ! concaténation de String var html =

    ''; html += '<div>Hello<span>'; html += username; html += '</span></div>'; $('#monelement').insert(html);
  16. <template>

  17. <template id="montemplate"> <img src=""> <div class="comment"></div> </template>

  18. parsé mais PAS AFFICHÉ <template id="montemplate"> <img src=""> <div class="comment"></div>

    </template>
  19. parsé mais PAS AFFICHÉ <script> ne s’EXÉCUTENT PAS <template id="montemplate">

    <img src=""> <div class="comment"></div> </template>
  20. 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>
  21. interface HTMLTemplateElement : HTMLElement { attribute DocumentFragment content; } <template>

  22. et pour l’INSTANCIER ? var t = document.querySelector('#montemplate'); t.content.querySelector('img').src =

    'http://...'; document.body.appendChild(t.content.cloneNode(true));
  23. 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));
  24. 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));
  25. 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));
  26. Encapsulation comment séparer le code que vous FOURNISSEZ de celui

    qui va le CONSOMMER
  27. L’Encapsulation d’aujourd’hui

  28. L’Encapsulation d’aujourd’hui <iframe>

  29. Par pitié NON !

  30. mais heureusement

  31. hadow DOM

  32. avec HTML5 <video controls src="/ma/super/video"></video>

  33. avec HTML5 == <video controls src="/ma/super/video"></video>

  34. 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>
  35. Déja là depuis LONGTEMPS le Shadow DOM est donc

  36. Déja là depuis LONGTEMPS Désormais ACCESSIBLE à tous les DÉVELOPPEURS

    Web le Shadow DOM est donc
  37. Instancier du shadow DOM <div id="host"> </div>

  38. 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>';
  39. 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>
  40. 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>
  41. Insertion points

  42. <content>

  43. shadow DOM <div>Je commence à apprendre les Web Components</div> <content></content>

    <div>J’ai fini d’apprendre les Web Components</div>
  44. 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>
  45. 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>
  46. 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
  47. 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>
  48. Shadow DOM et CSS

  49. <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>
  50. <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>
  51. <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>
  52. <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>
  53. Customiser le Scope des CSS shadowDom.applyAuthorStyles

  54. Customiser le Scope des CSS shadowDom.applyAuthorStyles Les styles EXTÉRIEURS sont

    APPLIQUÉS au shadow DOM
  55. Customiser le Scope des CSS shadowDom.resetStyleInheritance

  56. Customiser le Scope des CSS shadowDom.resetStyleInheritance Les styles du SHADOW

    DOM HÉRITENT des STYLES de la page
  57. et pour Styler l’élément host ?

  58. et pour Styler l’élément host ? <style> @host { /*

    Le style de l'élément host */ } </style>
  59. Custom Elements

  60. <megabutton>Mega Button?</megabutton>

  61. <element>

  62. <element name="megabutton" constructor="MegaButton"> </element>

  63. <element name="megabutton" constructor="MegaButton"> <template> <style>...</style> <content></content> </template> </element>

  64. <element name="megabutton" constructor="MegaButton"> <template> <style>...</style> <content></content> </template> <script> MegaButton.prototype =

    { doSomething: function() {…} }; </script> </element>
  65. <element name="megabutton" constructor="MegaButton"> <template> <style>...</style> <content></content> </template> <script> MegaButton.prototype =

    { doSomething: function() {…} }; </script> </element> <link rel="component" href="megabutton.html"> !
  66. <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> !
  67. <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>
  68. None
  69. Cycle de vie des Custom Elements created attributeChanged inserted removed

  70. 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>
  71. Mutation Observer observer le DOM

  72. 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); } }); });
  73. 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);
  74. les Mutation observers servent à MONITORER les insertions et suppressions

    d’éléments du DOM
  75. les Mutation observers REMPLACENT les MutationEvent

  76. les Mutation observers sont plus PERFORMANTS que les MutationEvent

  77. 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);
  78. Object.observe() observer le Modèle Javascript

  79. Object.observe() MONITORER les modifications des objets Javascript

  80. 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]); }); }
  81. 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);
  82. Model-Driven-View <html> <head> <script> var maValeur = "World !"; </script>

    </head> <body> <div> <h1>Hello {{maValeur}}</h1> </div> </body> </html>
  83. Performances AngularJS Dirty Checking VS Object.observe

  84. État actuel les Web Components dès Maintenant

  85. None
  86. AngularJS La Philosophie WEB COMPONENTS

  87. AngularJS La Philosophie WEB COMPONENTS DÉCLARATIF plutôt qu’IMPÉRATIF

  88. AngularJS La Philosophie WEB COMPONENTS DÉCLARATIF plutôt qu’IMPÉRATIF Une EXTENSION

    du LANGAGE HTML
  89. AngularJS La Philosophie WEB COMPONENTS DÉCLARATIF plutôt qu’IMPÉRATIF Une EXTENSION

    du LANGAGE HTML DIRECTIVES AngularJS == Web Components CUSTOM ELEMENTS
  90. 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
  91. Polymer Project

  92. 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
  93. Polymer & ANGULAR JS GOOGLE I/O 2013

  94. Polymer.Dart

  95. 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; } }
  96. Firefox & CO

  97. Firefox & CO

  98. None
  99. Demo Time !

  100. Disclaimer Ne CROYEZ pas tout ce que je vous ai

    dit VÉRIFIEZ le
  101. @julienvey That’s all folks