Introduksjon til – Web Components



Introduksjon til – Web Components

0 0


web-components-presentation

reveal.js

On Github jedimorten / web-components-presentation

Introduksjon til

Web Components

https://bit.ly/webcib

Program

Intro til web components Pause Polymer Olivia

HTML før HTML5

HTML før HTML5

						
							<div class="wrapper">
							    <div class="header">
							        <div class="innerheadwrapper">
							            <div class="innerheader"></div>
							            <div class="navbar"></div>
							        </div>
							    </div>
							    <div class="sidebar">
							        <div class="innersidebarwrapper"></div>
							    </div>
							    <div class="section">
							        <div class="contentwrapper">
							            <div class="content"></div>
							            <div class="content"></div>
							        </div>
							    </div>
							    <div class="footer"></div>
							</div>
						
					

HTML5!

HTML5

<!DOCTYPE html>
<html>
  <head></head>
  <body>
    <header></header>
    <nav></nav>
    <section></section>
    <article></article>
    <aside></aside>
    <footer></footer>
  </body>
</html>

Vis hvordan vi bruker HTML5 i slidene

HTML5

Bedre layout

HTML5

						<div class="wrapper">
    <header>
        <div class="innerheadwrapper">
            <div class="header"></div>
            <nav></nav>
        </div>
    </header>
    <aside>
        <div class="innersidebarwrapper"></div>
    </aside>
    <article>
        <div class="contentwrapper">
            <section></section>
            <section></section>
        </div>
    </article>
    <footer></footer>
</div>
					

Hva er likheten?

Hva er likheten?

<section> is the new <div>

Problemer?

Tradisjonelt webSIDE syntax

Globale variabler

DOM?

Document Object Model

  • Plattform-uavhengig
  • Trestruktur / DOM-tre
  • Forbindelse mellom kode og layout
  • HTML / XML

Globale variabler?

DOM

CSS

Hva gjør css vanskelig?

  • vertikal sentrering
  • browserstøtte
  • alle tricks og hacks man må huske
  • velvel... ikke egentlig, alt dette er ting google/god hukommelse kan hjelpe deg med.

Hva gjør egentlig css vanskelig?

  • scoping
  • specificity
  • dependency / avhengigheter
  • sletting av ubrukt kode

Så problemet er:

#selector .class ul li

Hva gjør man?

Facebook

Hva hadde vært kjekt?

Web-app-syntaks

Komponenter

Scoping

Tid: 15min

Fire nye standarder

Templates

Shadow DOM

Custom elementer

HTML import

Templates

Dagens workarounds:

Skjult DOM

Overloading script

Skjult DOM

						
							<div id="mytemplate" style="display: none;">
							    <img src="logo.png">
							    <div class="comment"></div>
							</div>
						
					

:) Bruker DOM

:) Ingenting blir rendra

:( Requests

:( Slitsomt å style

Overloading script

						
							<script id="mytemplate" type="text/x-handlebars-template">
							    <img src="logo.png"/>
							    <div class="comment"></div>
							</script>
						
					

:) Ingenting blir rendra

:) Ingen requests

:( Sikkerhetsproblemer

Webcomponent-style templating

						
						    <template id="mytemplate">
						        <img src="logo.png">
						        <div class="comment"></div>
						    </template>
						
					

:) Bruker DOM

:) Ingenting blir rendret

:) Ingen requests

:( Dårlig browserstøtte

Into the shadow

Skjule støy

Rydde i DOM

Vedlikeholdbart

Into the shadow

Vis Chrome shadow DOM

Into the shadow

						
							//Hent ut template fra tidligere
							var template = document.querySelector("#contact-template");
						
					
						
							//Hent ut mål-elementet
							var host = document.querySelector('contact-wrapper');
						
					
						
							//Lag en shadow root-node på mål-elementet
							var root = host.createShadowRoot();
						
					
						
							//Klon innholdet og barn-noder, og legg til i shadow DOM
							var clone = document.importNode(template.content, true);
							root.appendChild(clone);
						
					

Into the shadow

Insertion points

						
						  <template id="contact-template">
						    <div class="contact-header">
						    	<content select="h2"></content>
						    	<content select="img"></content>
						    </div>
						    <div class="detailed-info">
						    	<content select="ul"></content>
						    </div>
						  </template>
						
					

Shadow DOM visualizer

Tid: 35min

Into the shadow

Styling

Adskilt fra resten av DOM

Styling av host/mål-elementet; :host

Styling av rot-elementet; ::shadow

Tilgang til intern styling; >>>

Shadow DOM er altså tilgjengelig fra utsiden

Kontrollerte forhold

Eksplisitt selecte shadow DOM

Into the shadow

Styling - :host

						
:host {
  opacity: 0.4;
}
:host(:hover) {
  opacity: 1;
}
:host(:active) {
  opacity: 1;
  background-color: blue;
}
						
					

Selecting into the shadow

Styling - ::shadow

						
						.contact-tile::shadow h2 {
						    color: red;
						}

						
					

Styling av shadow DOM fra utsiden

Velger rot-elementet / shadow root

Selecting into the shadow

Shadow-piercing descendant combinator

Velger alle matchende elementer

Kraftigere enn ::shadow

/deep/ forsvinner, erstattes med:

>>> - null nettleserstøtte

Selecting into the shadow

Styling - /deep/ >>>

						

.contact-tile /deep/ .detailed-info{
  
}

.contact-tile >>> .detailed-info{
  
}
						
					

/deep/ velger alle elementene i alle shadow DOMs

Browser support

Custom Elementer

  • navne-konvensjon
  • kan utvide eksiterende html-elementer
  • kan benytte seg av templates og shadow dom
  • life-cycle callbacks

Custom Elements

						
							<button is="unclickable-button">Ikke prøv å klikk på meg</button>
						
					
Ikke prøv å klikk på meg

Life-cycle callbacks

  • createdCallback - instans av element opprettet.
  • attachedCallback - instans av element lagt til DOM
  • detachedCallback - instans fjerne fra DOM
  • attributeChangedCallback - atributt på element lagt til/fjernet/endret

Tid: 45min

Life-cycle events/callbacks

						
							var proto = Object.create(HTMLButtonElement.prototype);
							proto.createdCallback = function() {
							    var self = this,
							        t = document.querySelector('#unclickable-template'),
							        shadow = self.createShadowRoot();
							        shadow.appendChild(document.importNode(t.content, true));
							    self.style.position = "absolute";
							    self.addEventListener('mouseover', function(e) {
							        self.style.top = '';
							        self.style.left = '';
							        self.style.top = Math.floor((Math.random() * 300) + 1)+'px';
							        self.style.left = Math.floor((Math.random() * 600) + 1)+'px';
							    });
							};
							document.registerElement('unclickable-button',
													    {prototype: proto,
													     extends: 'button'}
													);
						
					

Html imports

Latest commit: Oops! This browser doesn't support Web Components.

						
						  Latest commit:
						  <time is="relative-time" datetime="2015-01-27T16:00:00.000Z">
						    Oops! This browser doesn't support Web Components.
						  </time>
						
					

Imports

						
							<link rel="import" href="dist/x-gif.html">
						
					
						
							<x-gif src="gifs/dog.gif" speed="5"></x-gif>
						
					

Tid: 55min

Html imports i praksis

Ekstern link?

Mappestruktur?

Droppe eksterne avhengigheter?

Ulemper med web components

Mye overhead, ikke deklarativt

Tidlig fase

Dårlig nettleserstøtte

Time for tasks

https://bit.ly/webcib

Polymer

Hvorfor Polymer?

Støtte for web components i "alle" nettlesere!

Hvorfor Polymer?

IE er ikke støttet fullt ut

Arkitektur

Applications

Custom elements

Core (Polymer.js)

Foundation (webcomponents.js)

Native

Arkitektur - Foundation

Polyfills for kjente egenskaper:

  • Shadow DOM
  • Custom Elements
  • HTML Imports
  • ++

Arkitektur

Applications

Custom elements

Core (Polymer.js)

Foundation (webcomponents.js)

Native

Syntaks

Vanilla vs Polymer

Attributter

Expressions

Touch events

Data binding

Lifecycle callbacks

Syntaks - Vanilla

Deklarer element

						
<template id="contact-template">
    <style></style>
</template>
<script>
    var proto = Object.create(HTMLElement.prototype),
        link = document.currentScript.ownerDocument;
        template = link.querySelector('#contact-template');
    proto.createdCallback = function() {
        //manage stuff
    };
    document.registerElement('contact-tile', {prototype: proto});
</script>
						
					

Bruk element

						
<contact-tile></contact-tile>
						
					

Syntaks - Polymer

Deklarer element

						
<polymer-element name="contact-tile">
    <template></template>
    <script>
        Polymer({
            //manage stuff
        });
    </script>
</polymer-element>
						
					

Syntaks

Attributes

Når man deklarerer et polymer-element har polymer reservert noen atributter:

  • name - registrer navnet på elementet
  • attributes - publiserte atributter
  • extends - om man utvider eksisterende elementer
  • noscript - om man lager et element uten behov for js
  • constructor - navn på javascript constructor, om man ønsker new CustomElement() i js.

Syntaks

Attributes

						
<polymer-element name="contact-tile" attributes="displayDetails favorite"></polymer-element>
						
					
						
Polymer({
    displayDetails: false,
    favorite: false
});
						
					

Tid: 1t 40min

Syntaks

Attributes

						
<polymer-element name="contact-tile"></polymer-element>
						
					
						
Polymer({
   publish: {
     displayDetails: {
       value: false,
       reflect: true
     },
     favorite: {
       value: false,
       reflect: true
     }
   }
 });
						
					

Tid: 1t 40min

Syntaks

Touch events

Kryssplattform

Mus + touch

Lite overhead

Syntaks

Touch events

						
							//Standard fra nettleser
							touch-action: auto;
							//Ingen touch
							touch-action: none;
							//Horizontal scrolling
							touch-action: pan-x;
							//Vertical scrolling
							touch-action: pan-y;
							//Pinch zoom + scrolling
							touch-action: manipulation;
						
					

Tid: 1t 50min

Syntaks

Touch events

						
							<div touch-action="auto"></div>
							<div touch-action="none"></div>
							<div touch-action="pan-x"></div>
							<div touch-action="pan-y"></div>
							<div touch-action="manipulation"></div>
						
					

Tid: 1t 50min

Syntaks

Data binding

Data binding - to-veis

						
							<polymer-element name="contact-tile">
							  <template>
							    {{name}} studerte på {{education}}
							  </template>
							  <script>
							    Polymer('contact-tile', {
							      ready: function() {
							        this.name = 'Yngve';
							        this.education = 'NTNU';
							      }
							    });
							  </script>
							</polymer-element>
						
					

Data binding - iterativt

						
<polymer-element name="contact-tile">
  <template>
    <ul>
      <template repeat="{{contact in contacts}}">
        <li>{{contact.name}}</li>
      </template>
    </ul>
  </template>
  <script>
    Polymer('contact-tile', {
      ready: function() {
        this.contacts = [
			  {'name': 'Morten Kjelling', 'position': 'Frontend / .NET'},
			  {'name': 'Yngve Svalestuen', 'position': 'Omni Capable'},
			  {'name': 'Bjørn Vegard Thoresen', 'position': '.NET'}
        ];
      }
    });
  </script>
</polymer-element>
						
					

Data binding - if

						
<polymer-element name="contact-tile">
  <template>
    <ul>
      <template if="{{!contacts.length}}">
        <li>Ingen kontakter!</li>
      </template>
    </ul>
  </template>
  <script>
    Polymer('contact-tile', {
      ready: function() {
        this.contacts = [];
      }
    });
  </script>
</polymer-element>
						
					

Data binding - eksplisitt binding

						
<polymer-element name="contact-tile">
  <template>
    <ul>
      <template repeat="{{contact in contacts}}">
	    <template if="{{contact.age > 25}}">
	      <div>{{contact.name}} er eldre enn 25år!</div>
	    </template>
	  </template>
    </ul>
  </template>
  <script>
    Polymer('contact-tile', {
      ready: function() {
        this.contacts = [
			  {'name': 'Morten Kjelling', 'age': 16},
			  {'name': 'Yngve Svalestuen', 'age': 24},
			  {'name': 'Bjørn Vegard Thoresen', 'age': 32}];
      }
    });
  </script>
</polymer-element>
						
					

Data binding - attributter

						
							<a href="{{url}}"></a>
						
					
  • Stort sett enveis
  • Toveis på input-elementer

Data binding - input-verdier

  • input: value, checked
  • option: value
  • select: selectedIndex, value
  • textarea: value

Data binding - published properties

						
<polymer-element name="contact-tile" attributes="name">
  <template>
    Navn: {{name}}
  </template>
  <script>
    Polymer('name-field', {
      ready: function() {
        this.name = 'Ukjent'
      }
    });
    </script>
</polymer-element>
<polymer-element name="contact-tile">
  <template>
    <p><name-field name="{{nameValue}}"></name-field></p>
    <p>Hva heter du? <input value="{{nameValue}}" placeholder="Skriv inn navnet ditt..."></p>
  </template>
</polymer-element>

<contact-tile></contact-tile>
						
					

Data binding - engangs

						
							<input type="text" value="Verdi som bare settes inn en gang: [[ value ]]">
						
					

Blir inaktiv etter første binding

Fordel for ytelsen

Eksperimentell!

Tid: 1t 50min

Syntaks

{{ Expressions }}

Gjøre enkle verdi konsepter

Filtrering

Kan ikke legge til HTML ved å bruke expressions

Hvor mange GIFs har Morten?

						
							<p>Morten har {{ folders.gif.length }} gifs</p>

						
							<p>Morten har 9001 gifs</p>

Tid: 1t 55min

Custom filter

						
						    {{ Hallo Navet | uppercase}}
						
					
						
							PolymerExpressions.prototype.uppercase = function(input) {
							    return input.toUpperCase();
							};
						
					

Sende inn parameter til filter

						
							{{myNumber | toFixed(2)}}
						
					
						
							toFixed: function(value, precision) {
								return Number(value).toFixed(precision);
							}
						
					

Lifecycle callbacks

Spec Polymer createdCallback created - ready The <polymer-element> has been fully prepared (e.g. shadow DOM created, property observers setup, event listeners attached, etc). attachedCallback attached - domReady Called when the element’s initial set of children are guaranteed to exist. This is an appropriate time to poke at the element’s parent or light DOM children. Another use is when you have sibling custom elements (e.g. they’re .innerHTML‘d together, at the same time). Before element A can use B’s API/properties, element B needs to be upgraded. The domReady callback ensures both elements exist. detachedCallback detached attributeChangedCallback attributeChanged

Elementer

Core

Paper

Google

++

Tid: 2t

Core

Paper

Google-elementer

googlewebcomponents.github.io/google-chart/

Google-elementer

googlewebcomponents.github.io/google-map/

Google-elementer

googlewebcomponents.github.io

customelements.io

Polymer Designer

polymer-designer.appspot.com

Tid: 2t 5min

Data-binding

Prototyping

Ulemper

Uferdig dokumentasjon

Fortsatt under utvikling

Feilhåndtering

Time for tasks

https://bit.ly/webcib

Spørsmål?

www.html5rocks.com

webcomponents.org

polymer-project.com

x-tags.org

Tid: 2t 15min

Data-binding

Prototyping

Jobb?

Ciber.no

Nina Orucevic / nina.orucevic@ciber.com

Takk for oss!