Web Components + Backbone: a Game-Changing Combination

Post on 12-Jul-2015

21,321 views 0 download

transcript

Web Components + BackboneA Game-Changing Combination

Who Am I?

Andrew RotaJavaScript Engineer,

JavaScript Modularity

By using small libraries –components with a dedicatedpurpose and a small surfacearea – it becomes possible topick and mix, to swap parts ofour front end stack... - Jimmy Breck-McKye, "The State of JavaScript in2015"

Modularity in HTML == DOM Elements

<ul>  <li>First Item</li>  <li>Second Item</li></ul>

<ol>  <li>First Item</li>  <li>Second Item</li></ol>

<div class="header"></div>

<header></header>

<div id="nav"></div>

<nav></nav>

Libraries > frameworks?- Jimmy Breck-McKye, "The State of JavaScript in2015"

Libraries > frameworks?- Jimmy Breck-McKye, "The State of JavaScript in2015"

Native functionality > libraries> frameworks.- Me

But creating your own elementsisn't possible...

... until now.

Web Componentsusher in a new era ofweb developmentbased onencapsulated andinteroperable customelements that extendHTML itself. - Polymer Project

Web Components

Web Component Technologies

Custom Elements

HTML Templates

HTML Imports

Shadow DOM

Web Component Technologies

Custom Elements

HTML Templates

HTML Imports

Shadow DOM

Custom Elements

<my‐element>Hello World.</my‐element>            

var MyElement = document.registerElement('my‐element', {  prototype: Object.create(HTMLElement.prototype)});            

Web Component Technologies

Custom Elements

HTML Templates

HTML Imports

Shadow DOM

HTML Templates<template id="my‐template">    <p>Hello World.</p>    <!‐‐ This image won't be downloaded on page load ‐‐>    <img src="example.jpg" alt="Example"></template>

document.importNode(    document.getElementById('my‐template').content,    true);

Web Component Technologies

Custom Elements

HTML Templates

HTML Imports

Shadow DOM

HTML Imports<link rel="import" href="/imports/my‐component.html">

Web Component Technologies

Custom Elements

HTML Templates

HTML Imports

Shadow DOM

Browser Shadow DOM

Shadow DOM<div id="my‐element"></div><p>Light DOM.</p>

// Create Shadow Rootvar s = document.getElementById('my‐element').createShadowRoot();// Add Styles and Texts.innerHTML += '<style>p { color: crimson; }</style>';s.innerHTML += '<p>Shadow DOM.</p>';

Shadow DOM.

Light DOM.

<content><div id="my‐element"><p>Hello!</p></div>

var s = document.getElementById('my‐element').createShadowRoot();s.innerHTML += '<p>Shadow DOM Start.</p>';s.innerHTML += '<style>p { color: crimson; }</style>';s.innerHTML += '<content></content>';s.innerHTML += '<p>Shadow DOM End.</p>';

Shadow DOM Start.Hello!

Shadow DOM End.

Web Component Technologies

Custom Elements

HTML Templates

HTML Imports

Shadow DOM

What Web Components Lack...

Application Structure

Server Interface

URL Router

Models/Collections + Events

...We Gain with Backbone

Application Structure

Server Interface

URL Router

Models/Collections + Events

Using WebComponent

Technologies+

Backbone

Backbone + Custom Elementsdocument.registerElement('my‐custom‐element', {  prototype: Object.create(HTMLElement.prototype)});

Backbone.View.extend({  tagName: 'my‐custom‐element'});

Backbone + HTML TemplatesBackbone.View.extend({  template: document.importNode(    document.getElementById('my‐template').content,    true  ),  render: function() {    this.el.innerHTML = this.template;  }});

Backbone + HTML Imports<link rel="import" href="my‐custom‐component.html">

Backbone + Shadow DOMBackbone.View.extend({  initialize: function() {    this.el.createShadowRoot();  }});

Using WebComponent

Technologies+

Backbone

Using WebComponents

+Backbone

polymer-project.org/docs/elements

x-tags.org

component.kitchen

customelements.io

Backbone View+

Web Component

<paper‐toast>

<paper‐toast> API

<paper‐toast  text="Your toast is ready!"  duration="5000"  autoCloseDisabled  opened></paper‐toast>

Element.show();Element.dismiss();Element.toggle();

Element.addEventListener('core‐overlay‐open‐completed', doSomething

Backbone.View.extend({  tagName: 'paper‐toast',  attributes: {    text: 'Your toast is ready!',    autoCloseDisabled: true,    duration: '5000',    opened: true  },  events: {    'core‐overlay‐open‐completed': 'doSomething'  },  toggle: function() {    this.el.toggle();  }});

<google‐map>

<google‐map> API

<google‐map  zoom="10"  latitude="42.3581"  longitude="‐71.0636"></google‐map>

Element.resize();Element.clear();

Element.addEventListener('google‐map‐ready', doSomething);

Backbone.View.extend({  tagName: 'google‐map',  attributes: {    latitude: '42.3581',    longitude: '‐71.0636',    zoom: '10'  },  events: {    'google‐map‐ready': 'doSomething'  },  resize: function() {    this.el.resize();  }});

Backbone.View.extend({  initialize: function() {    this.listenTo(this.model, 'change', this.moveMap );  },  tagName: 'google‐map',  moveMap: function(model) {    this.el.setAttribute('latitude', this.model.get('lat'));    this.el.setAttribute('longitude', this.model.get('long'));    this.el.setAttribute('zoom', this.model.get('zoom'));  }});

Building Web Componentsfor Backbone (or anything else)

├── hello‐world├──── hello‐world.html├──── hello‐world.js└──── bower.json            

<template id="my‐template">  Hello, <content></content</template><script src="hello‐world.js

var element = Object.create(HTMLElement.prototype);

element.createdCallback = function() {};

element.attachedCallback = function() {};

element.attributeChangedCallback = function(attr, oldVal, newVal) {}

element.detachedCallback = function() {};

document.registerElement('hello‐world', {  prototype: element});

<link  rel="import"  href="components/hello‐world/hello‐world.html>

<!‐‐ [...] ‐‐>

<hello‐world>I'm a web component</

How It All Fits Together

Application + Components

Application

Component Component Component Component Component

Component Component Component Component Component

Component Component Component Component Component

Application + Components

Application + Components

Application + Components

< X >

< X >

Web Component All the Things??<backboneconf‐app>    <backboneconf‐menu></backboneconf‐menu>    <backboneconf‐content></backboneconf‐content>    <backboneconf‐footer></backboneconf‐footer></backboneconf‐app>

Probably Not (and that's OK)

I don't ever see us going all inon Custom Elements for everypossible thing ... Use nativeelements and controls whenpossible and supplement withcustom elements. - Joshua Peek, Github Programmer

Should I Componentize?Does it encapsulate component-level logic?

Does it take the place of a native element?

Should it be portable?

Is it context independent?

Can the API be represented as attributes, methods, and events?

Small

Open for Extension

Documented

Unit Tested

Accessible

Idempotent

Best Practices

Can I Use???Custom

ElementsHTML

TemplatesHTML

ImportsShadow

DOM

✓ ✓ ✓ ✓

✓ ✓ ✓ ✓

Flag ✓ Flag Flag

X ✓ X X

X X X X

Can I Use???Custom

ElementsHTML

TemplatesHTML

ImportsShadow

DOM

✓ ✓ ✓ ✓

✓ ✓ ✓ ✓

✓ ✓ ✓ ✓

✓ ✓ ✓ ✓

✓ ✓ ✓ ✓

webcomponents.js

Towards a Component Driven Web

Thanks!

Resources- WebComponents.org- Web Components: A Tectonic Shift for Web Development by Eric Bidelman- Web Components by Jarrod Overson and Jason Strimpel- Ten Principles for Great General Purpose Web Components

Colophon

This presentation was built with Backbone.js, Shadow DOM, HTMLTemplates, HTML Imports, and the Custom Element <slide‐content>using Web Component Slides.