web components
TRANSCRIPT
© Copyright SELA Software & Education Labs, Ltd. | 14-18 Baruch Hirsch St., Bnei Brak, 51202 Israel | www.selagroup.com
SELA DEVELOPER PRACTICEDecember 28th – January 1st, 2014
Noam Kfir
Web Components
Pseudo-semantic HTML
Very poor separation of concerns
A script language expected to behave like a “real” language
Inconsistent browser implementations
A huge variety of target devices and platforms
Modern Web Development
It’s a total freakin’ MESS!
Web Components to the Rescue
A set of standards designed to componentize the web
Some general goals:
code reuse,encapsulation,
SoC
UI composition,
theming
more expressive,semantic
Part of the Ecosystem
Shares some features with existing frameworks and librariesMustache, Handlebars, Angular, Knockout, and many others
But universal:HTML5
Standard
Portable
Extensible
And growing fast!
The Web Components Standards
•roll your own elementsCustom Elements
•reusable DOM fragmentsHTML Templates
•DOM encapsulationShadow DOM
•load HTML declarativelyHTML Imports
The State of Web Components
W3C Working Drafts
Mixed browser support:http://caniuse.com/#search=web%20components
Polyfills
Polymer X-Tag Bosonic
Browsers have only partial support, unpredictable
So we use the webcomponents.js polyfill
> bower install --save webcomponentsjs
Installation
Reference the webcomponents.js script in the <head> tag
Make sure it’s the first script
<head>
<script src="bower_components/webcomponentsjs/webcomponents.js"></script>
</head>
Installation
HTML Imports Overview
Include HTML documents in other HTML documents
Can be used to import any HTML
Especially useful with Custom Elements
Replaces old kludges:
IFrame
HTML script element <script type="text/html"></script>
Ajax $(target).load("source.html selector");
HTML Imports Lifecycle
The outer HTML is loaded and parsed
After DOMContentLoaded, the polyfill loads the imports
After imports are loaded, HTMLImportsLoaded is fired
After the data is parsed, WebComponentsReady is fired
Polyfill lifecycle is a a bit different from native lifecycle
DOMContentLoaded HTMLImportsLoaded WebComponentsReady
Reference the polyfill first
Use the <link rel="import" /> tag to declare an import
Process the import in the HTMLImportsLoaded event handler
<head>
<script src="bower_components/webcomponentsjs/webcomponents.js"></script>
<link rel="import" href="imported.html" id="content" />
<script>
document.addEventListener('HTMLImportsLoaded', function(e) {
var contentDocument = document.getElementById('content').import;
var content = contentDocument.querySelector('.content');
var cloned = content.cloneNode(true);
</script>
</head>
HTML Imports Overview
Additional Notes
Scripts running inside the import can reference the containing document by calling document.currentScript.ownerDocument
In a polyfilled environment: document._currentScript.ownerDocument
CORS constraints apply to documents imported from other domains
Don’t forget to clone the nodes you want to import
Roll Your Own
Custom Elements make a truly semantic web possible
You can create elements named (almost) any way you want:
Same naming rules as other tags
There must be a dash (“-”) in the name to future-proof the name against the HTML standard and avoid naming collisions
Custom Elements can also be used to “upgrade” existing elements and add additional behavior
Register the element with prototype and extend
document.registerElement('sela-syllabus', {
prototype: Object.create(HTMLUListElement.prototype),
extends: 'ul'
});
Extend an Existing Element
And then associate it with the extended element
<ul is="sela-syllabus"></ul>
Extend an Existing Element
Custom Element Callbacks
createdCallbackcalled when an instance is created
attachedCallbackcalled when an instance is added to DOM subtree
detachedCallbackcalled when an instance is removed from a DOM subtree
attributeChangedCallbackcalled after an attribute value changes
Separation of Concerns
Separate the view (HTML/CSS) from its logic (JS)
Represented with the <template> tag
Templates are loaded in an “inert” stateready to be cloned
scripts don’t run
resources aren’t loaded
Templates can be placed almost anywhere, including imports
Put the templated content inside the template element
The template will usually be just part of a custom element
<template id="template">
<style>
...
</style>
<div>
<h1>Web Components</h1>
<img src="http://webcomponents.org/img/logo.svg">
</div>
</template>
Using the <template> tag
The template’s container has to import the template.contentnode, which does a deep clone
The new element is then added to the DOM and activated
<script>
var template = document.querySelector('#template');
var clone = document.importNode(template.content, true);
var host = document.querySelector('#host');
host.appendChild(clone);
</script>
<div id="host"></div>
Cloning the template
Data Binding
Templates do not support data binding
Polymer, X-Tag and other polyfills provide data binding support
Understanding the Shadow DOM
Separates a logical tree from a visual tree
(it’s actually more complex, but that’s the general idea)
Provides encapsulation
The Custom Element can hide its own logic internally and expose an API
Makes the element more portable
Elements can be nested inside and outside the shadow DOM
Vulcanize
Custom Elements embed multiple resources
Browsers use threads to download resources, but they only have a few available threads
Using custom elements can severely degrade page download performance
Vulcanize can flatten the Web Components to produce fewer requests
Can be added to a grunt/gulp build
Web Components can be heavy!
HTML
CSS
JavaScript
Nested elements
Media files
Web Components represent the baseline for the new web
Provide encapsulation, SoC, UI composition, portability and extensibility, and lots of other features
Not yet finalized – still Working Draft
A moving target, but there are some production examples
There are actually multiple standards that can be used independently of each other
Summary