Web Components v1
-
Upload
mike-wilcox -
Category
Technology
-
view
460 -
download
0
Transcript of Web Components v1
![Page 1: Web Components v1](https://reader031.fdocuments.net/reader031/viewer/2022022419/589ecad31a28ab47138b5b69/html5/thumbnails/1.jpg)
CLUB AJAX
![Page 2: Web Components v1](https://reader031.fdocuments.net/reader031/viewer/2022022419/589ecad31a28ab47138b5b69/html5/thumbnails/2.jpg)
by Mike Wilcox, January 2017
Web Components and ES6 Classes
![Page 3: Web Components v1](https://reader031.fdocuments.net/reader031/viewer/2022022419/589ecad31a28ab47138b5b69/html5/thumbnails/3.jpg)
JS Frameworks• Some more mobile friendly than others
• Although hard to say that any of them truly are • Jeff Atwood complains about poor Ember perf for Discourse
• Isomorphic/Universal Apps using server side rendering • Creates faster visual content on the page • But also creates a “valley of death” where the page is no functional
• Virtual DOM can sometimes be effective • Sometimes effective • Sometimes not
• On demand loading • Some frameworks support it, some don’t
![Page 4: Web Components v1](https://reader031.fdocuments.net/reader031/viewer/2022022419/589ecad31a28ab47138b5b69/html5/thumbnails/4.jpg)
![Page 5: Web Components v1](https://reader031.fdocuments.net/reader031/viewer/2022022419/589ecad31a28ab47138b5b69/html5/thumbnails/5.jpg)
Dojo
![Page 6: Web Components v1](https://reader031.fdocuments.net/reader031/viewer/2022022419/589ecad31a28ab47138b5b69/html5/thumbnails/6.jpg)
Dojo<div class='createSection' data-dojo-attach-point='createSection'> <div class='row'> <div data-dojo-attach-point="filterName" data-dojo-type="app/components/ui/TextFilter" data-dojo-props="fieldLabel:'${messages.filterName}', required: true”>
![Page 7: Web Components v1](https://reader031.fdocuments.net/reader031/viewer/2022022419/589ecad31a28ab47138b5b69/html5/thumbnails/7.jpg)
Dojo<div class='field'> ${labelNode} <div data-dojo-attach-point="textbox" class='fieldWidget' data-dojo-type="dijit/form/TextBox" data-dojo-attach-event="onKeyUp: _update"></div> </div>
![Page 8: Web Components v1](https://reader031.fdocuments.net/reader031/viewer/2022022419/589ecad31a28ab47138b5b69/html5/thumbnails/8.jpg)
define([ 'dojo/_base/declare', 'dx/Widget', 'dojo/text!./templates/TextFilter.html', 'dijit/form/TextBox'], function(declare, Widget, template) { return declare(Widget, { templateString: template, postMixInProperties: function(){ }, postCreate: function(){ }, focus: function(){ this.textbox.focus(); }, _setValueAttr: function(value){ this.textbox.set('value', value); }, _getValueAttr: function(){ return this.textbox.get('value'); },
Dojo
![Page 9: Web Components v1](https://reader031.fdocuments.net/reader031/viewer/2022022419/589ecad31a28ab47138b5b69/html5/thumbnails/9.jpg)
Ember
![Page 10: Web Components v1](https://reader031.fdocuments.net/reader031/viewer/2022022419/589ecad31a28ab47138b5b69/html5/thumbnails/10.jpg)
Ember<div class="client-page"> {{side-nav nav=navigation clientId=model.client.id}}
![Page 11: Web Components v1](https://reader031.fdocuments.net/reader031/viewer/2022022419/589ecad31a28ab47138b5b69/html5/thumbnails/11.jpg)
Ember<div class="nav-items"> {{#each nav as |link|}} {{#unless (eq link.state "hidden") }} {{#if (eq link.state "disabled") }} <div class="side-nav-link {{link.state}}"> <div class="side-nav-title">{{link.title}}</div> </div> {{else}} {{#link-to link.route title=link.title class=link.state}} <div class="side-nav-link {{link.state}}"> <div class="side-nav-title">{{link.title}}</div> </div> {{/link-to}} {{/if}} {{/unless}} {{/each}} </div>
![Page 12: Web Components v1](https://reader031.fdocuments.net/reader031/viewer/2022022419/589ecad31a28ab47138b5b69/html5/thumbnails/12.jpg)
Emberimport Ember from ‘ember'; import Navigation from '../../mixins/navigation'; export default Ember.Component.extend(Navigation, { classNames: ['side-nav'], nav: null, clientId: ‘NA’,
activeNavigation: Ember.computed('navigation', function () { let activeNavigationObject = []; this.get('navigation').forEach((mainItem)=> { ... }); return activeNavigationObject;}),
});
![Page 13: Web Components v1](https://reader031.fdocuments.net/reader031/viewer/2022022419/589ecad31a28ab47138b5b69/html5/thumbnails/13.jpg)
Angular 2
![Page 14: Web Components v1](https://reader031.fdocuments.net/reader031/viewer/2022022419/589ecad31a28ab47138b5b69/html5/thumbnails/14.jpg)
Angular<div [ngBusy]="{busy: busy, message: 'Please wait...'}"> <div *ngIf="settingView"> <my-actions [links]="settingView.actionUrls"></my-actions> </div> </div>
![Page 15: Web Components v1](https://reader031.fdocuments.net/reader031/viewer/2022022419/589ecad31a28ab47138b5b69/html5/thumbnails/15.jpg)
Angular<h4>Actions</h4> <div class="section"> <a href="{{links[0]}}">Change Your Password</a> <a href="{{links[1]}}">Change Your Security Questions</a> <a href="{{links[2]}}">Change other usernames for a Single Sign-On Experience</a> </div>
![Page 16: Web Components v1](https://reader031.fdocuments.net/reader031/viewer/2022022419/589ecad31a28ab47138b5b69/html5/thumbnails/16.jpg)
Angularimport { Component, Input, OnInit } from '@angular/core'; @Component({ moduleId: module.id.toString(), selector: 'my-actions', templateUrl: 'actions.component.html'}) export class ActionsComponent implements OnInit { constructor() { } @Input() links: string[] = []; ngOnInit() { }}
![Page 17: Web Components v1](https://reader031.fdocuments.net/reader031/viewer/2022022419/589ecad31a28ab47138b5b69/html5/thumbnails/17.jpg)
React
![Page 18: Web Components v1](https://reader031.fdocuments.net/reader031/viewer/2022022419/589ecad31a28ab47138b5b69/html5/thumbnails/18.jpg)
Reactimport React from 'react'; import { render } from 'react-dom'; import Text from './form-sections/text'; export default class Form extends React.Component { constructor(props) { super(props); } render() { return ( <ay-form ref="form"> <Text /> </ay-form> ); }}
![Page 19: Web Components v1](https://reader031.fdocuments.net/reader031/viewer/2022022419/589ecad31a28ab47138b5b69/html5/thumbnails/19.jpg)
Reactimport React from 'react'; import { render } from 'react-dom'; import pure from 'react-addons-pure-render-mixin'; export default class Text extends React.Component { constructor(props) { super(props); this.shouldComponentUpdate = pure.shouldComponentUpdate.bind(this); } render() { return ( <section> <ay-field type="text" value="" name="where" placeholder="Where"></ay-field> </section> ); }}
![Page 20: Web Components v1](https://reader031.fdocuments.net/reader031/viewer/2022022419/589ecad31a28ab47138b5b69/html5/thumbnails/20.jpg)
jQuery
![Page 21: Web Components v1](https://reader031.fdocuments.net/reader031/viewer/2022022419/589ecad31a28ab47138b5b69/html5/thumbnails/21.jpg)
React<div class="jq-picker"></div> <script> $.ready(function(){ $(".jq-picker").jqPicker(options); });</script>
![Page 22: Web Components v1](https://reader031.fdocuments.net/reader031/viewer/2022022419/589ecad31a28ab47138b5b69/html5/thumbnails/22.jpg)
JS Frameworks + Web Components• Web Components are “just HTML” so they will work with all of them
• It may require some manual wiring, like using addEventListener
• With plugins, you can make use of framework template functionality • https://github.com/webcomponents/react-integration • https://github.com/clubajax/react-inject-change-events
![Page 23: Web Components v1](https://reader031.fdocuments.net/reader031/viewer/2022022419/589ecad31a28ab47138b5b69/html5/thumbnails/23.jpg)
What are they?
![Page 24: Web Components v1](https://reader031.fdocuments.net/reader031/viewer/2022022419/589ecad31a28ab47138b5b69/html5/thumbnails/24.jpg)
Web Components Benefits• Part of the DOM - lifecycle tools for free!
• Future-proof and cross-browser (web standard) for creating and extending reusable components.
• Requires no library or framework to get started. Vanilla JS/HTML FTW!
• Provides a familiar programming model. It's just DOM/CSS/HTML.
• Creates a very modular system
• Tightly integrated with the browser's DevTools.
• Leverage existing accessibility features.
![Page 25: Web Components v1](https://reader031.fdocuments.net/reader031/viewer/2022022419/589ecad31a28ab47138b5b69/html5/thumbnails/25.jpg)
Web Components• Custom Elements
• Shadow DOM
• Templates
• HTML Imports
All four of these items are a WC3 spec, all of which makes up Web Components
![Page 26: Web Components v1](https://reader031.fdocuments.net/reader031/viewer/2022022419/589ecad31a28ab47138b5b69/html5/thumbnails/26.jpg)
Custom Elements• Define your own element types and functionality • Provides a standard way to associate JavaScript logic with an
element • Lifecycle methods • No confusing context — “this” is the element • Easy to inspect in debuggers
We could do custom elements with IE6… the difference is the life cycle methods
<x-tabs> <ul>Tab 1</ul> <ul>Tab 2</ul> <ul>Tab 3</ul> </x-tabs>
![Page 27: Web Components v1](https://reader031.fdocuments.net/reader031/viewer/2022022419/589ecad31a28ab47138b5b69/html5/thumbnails/27.jpg)
Shadow DOM
Content can be “projected” into provided slots
• Shadow DOM refers to the ability of the browser to include a subtree of DOM elements into the rendering of a document, but not into the main document DOM tree.
• CSS style rules are constrained to the shadow tree they were defined in.
• The DOM is also encapsulated. For example, document.querySelectorAll('div'); will not return any results from a custom element with Shadow DOM
![Page 28: Web Components v1](https://reader031.fdocuments.net/reader031/viewer/2022022419/589ecad31a28ab47138b5b69/html5/thumbnails/28.jpg)
Templates• The template element is used to declare fragments of HTML
that can be cloned and inserted in the document by script.
• Contains a DocumentFragment in its HTMLTemplateElement.content property
![Page 29: Web Components v1](https://reader031.fdocuments.net/reader031/viewer/2022022419/589ecad31a28ab47138b5b69/html5/thumbnails/29.jpg)
HTML Imports
<link rel=“import” href=“./my-bugger.html” /> <link rel=“import” href=“./my-zapper.html” />
• Can import all in one file: JavaScript, HTML, and CSS
• Effectively, an HTML document.
• HTML Imports can be the dependency management system, replacing AMD or CommonJS
• HTML Imports let you include and reuse HTML documents in other HTML documents, just as script tags let you include external JavaScript in their pages.
![Page 30: Web Components v1](https://reader031.fdocuments.net/reader031/viewer/2022022419/589ecad31a28ab47138b5b69/html5/thumbnails/30.jpg)
HTML Imports - CONS
The HTML Import spec does not have consensus. Mozilla is still holding out, after two years.
<link rel=“import” href=“./my-bugger.html” /> <link rel=“import” href=“./my-zapper.html” />
• Confusing context when importing templates
• Spec essentially competes with ES modules
• Globals
![Page 31: Web Components v1](https://reader031.fdocuments.net/reader031/viewer/2022022419/589ecad31a28ab47138b5b69/html5/thumbnails/31.jpg)
Can I use…?
![Page 32: Web Components v1](https://reader031.fdocuments.net/reader031/viewer/2022022419/589ecad31a28ab47138b5b69/html5/thumbnails/32.jpg)
Browser Support• Chrome v54
• WebKit Nightly v18
• Edge has begun prototyping
• Firefox has an open bug
![Page 33: Web Components v1](https://reader031.fdocuments.net/reader031/viewer/2022022419/589ecad31a28ab47138b5b69/html5/thumbnails/33.jpg)
Browser Stats
![Page 34: Web Components v1](https://reader031.fdocuments.net/reader031/viewer/2022022419/589ecad31a28ab47138b5b69/html5/thumbnails/34.jpg)
We need to support old IE because we…• want to expose our servers to unsupported, insecure browsers.
• like to pay the extra IE development cost (8:25%, 9:10%, 10:5%).
• enjoy tying up QA to spend extra time testing more browser versions
https://www.xfive.co/blog/stop-supporting-ie10-ie9-ie8/
Seriously, management often encourages the support of old versions because they are not aware of the cost and risk.
![Page 35: Web Components v1](https://reader031.fdocuments.net/reader031/viewer/2022022419/589ecad31a28ab47138b5b69/html5/thumbnails/35.jpg)
Polyfills• A polyfill for HTML Custom Elements.
• ShadyDOM provides a shim for ShadowDOM V1. It is less correct but less intrusive and faster than the ShadowDOM Polyfill.
• ShadyCSS provides a shim for CSS Custom Properties, CSS Mixins with @apply support, and ShadowDOM V1 style encapsulation with the ShadyDOM library.
![Page 36: Web Components v1](https://reader031.fdocuments.net/reader031/viewer/2022022419/589ecad31a28ab47138b5b69/html5/thumbnails/36.jpg)
v0 vs v1*
*The differences between the old spec and the recent changes
![Page 37: Web Components v1](https://reader031.fdocuments.net/reader031/viewer/2022022419/589ecad31a28ab47138b5b69/html5/thumbnails/37.jpg)
v0var proto = Object.create(HTMLElement.prototype);proto.createdCallback = function() { // invoked on creation}; proto.attachedCallback = function() { // invoked when added to the document}; proto.detachedCallback = function() { // invoked when removed from the document}; proto.attributeChangedCallback = function(attrName, oldVal, newVal) { // invoked when an attribute is changed}; var MyComponent = document.registerElement('my-component', { prototype: proto});
![Page 38: Web Components v1](https://reader031.fdocuments.net/reader031/viewer/2022022419/589ecad31a28ab47138b5b69/html5/thumbnails/38.jpg)
class MyComponent extends HTMLElement { static get observedAttributes() { return ['value', 'disabled']; } constructor ( ) { super(); } connectedCallback ( ) { } disconnectedCallback ( ) { } attributeChangedCallback(attrName, oldVal, newVal) { } adoptedCallback() { }} customElements.define('my-component', MyComponent);
v1 constructor: the element is created or upgraded
connectedCallback: the element is inserted into the DOM
disconnectedCallback: the element is removed from the DOM.
attributeChangedCallback: an attribute was added, removed, or updated
adoptedCallback the element has been moved into a new document
define: exposes the element name for use in markup
![Page 39: Web Components v1](https://reader031.fdocuments.net/reader031/viewer/2022022419/589ecad31a28ab47138b5b69/html5/thumbnails/39.jpg)
HistoryQ: Why did the spec change?
A: The old spec did not work with ES6 classes
Q: Does the new spec work wth ES5?
A: uh, sort of…
Q: Who changed it?
A: Blame Apple's Ryosuke Niwa. He’s made a few changes…
Q: Should I wait to use Web Components until v1 is implemented?
A: No, not any more than you would wait for any other shim-able browser feature
![Page 40: Web Components v1](https://reader031.fdocuments.net/reader031/viewer/2022022419/589ecad31a28ab47138b5b69/html5/thumbnails/40.jpg)
Inheritance
class MyButton extends HTMLButtonElement { constructor () { super(...arguments); }} customElements.define('my-button', MyButton, {extends: 'button'});
Extends something other than HTMLElement
Extra argument when defining
Blocked by Apple.
Use native tag, and extended tag in “is”
This is what it would look like… if it were implemented.
![Page 41: Web Components v1](https://reader031.fdocuments.net/reader031/viewer/2022022419/589ecad31a28ab47138b5b69/html5/thumbnails/41.jpg)
ES6 Classes
class MyComponent extends HTMLElement { static something () { return 'something'; } constructor () { super(); } connectedCallback () { // } }
always call super() first in the constructor. “this” is not established until after
Commas are forbidden to emphasize that class definitions are different from object literals.
Classes are sugar for prototypal inheritance. MyComponent is a function that inherits from the HTMLElement prototype.
static is similar to: MyComponent.something = function () {
return ’something’;}
data properties are not allowed like in objects: {a: true} (yet) getters and setters must be used.
super is used as a function in the constructor, as property references: super.someMethod();
![Page 42: Web Components v1](https://reader031.fdocuments.net/reader031/viewer/2022022419/589ecad31a28ab47138b5b69/html5/thumbnails/42.jpg)
Custom Element API Considerations• Sync important properties with attributes
• getters/setters over methods
• Broadcast changes via events
• Use standard properties and event names (“value”, “change”)
• innerHTML — what happens, before and after initialization?
• Appending children
• Use :defined or alternative
• Consider Shadow DOM styling pros and cons
![Page 43: Web Components v1](https://reader031.fdocuments.net/reader031/viewer/2022022419/589ecad31a28ab47138b5b69/html5/thumbnails/43.jpg)
DEMOS
![Page 44: Web Components v1](https://reader031.fdocuments.net/reader031/viewer/2022022419/589ecad31a28ab47138b5b69/html5/thumbnails/44.jpg)
Refshttps://github.com/webcomponents/shadydom
https://github.com/webcomponents/shadycss
https://webkit.org/blog/7027/introducing-custom-elements/
https://github.com/webcomponents/react-integration
https://github.com/clubajax/react-inject-change-events
https://hacks.mozilla.org/2014/12/mozilla-and-web-components/
https://www.polymer-project.org/1.0/blog/2016-12-21-polymer-2.0-update
https://developers.google.com/web/fundamentals/getting-started/primers/customelements?hl=en#historysupport
https://twitter.com/AaronGustafson/status/717028669948977153
https://github.com/w3c/webcomponents/issues/509
![Page 45: Web Components v1](https://reader031.fdocuments.net/reader031/viewer/2022022419/589ecad31a28ab47138b5b69/html5/thumbnails/45.jpg)
CLUB AJAX