Sergio Marin
@highercomve
Nobody special, my name is Sergio Marin and I'm a web developer just like you.
I Work at uBiome as Technical Lead for Patient Portal
The main reason is because they break the composition rule
Composition with different frameworks is kinda crazy, you will end up having cross dependencies everywhere.
Those solutions have their own implementation of components, you can't simply add the component in your HTML by only adding the component.
If you create a Vue component you need Vue to run it, if you create a React component you need React to run it and so.
But your browser supports already custom elements, where you can create an HTML tag and to that, you can add logic, listeners, and everything that the web already does and those components will work in any (*) browser.
What is a component?
Do we use them now?
Lets resume 17 rules on 7 rules
We are going to use it, is inevitable, the idea in this talk is to speak about the underlying technology that maybe will be used in the future by our well know framework.
It would be great to have at least a close idea of how the web platform is evolving , how the browser right now supports web components and how that could change the way we write web applications today.
The template element is used to declare fragments of HTML that can be cloned and inserted into the document by script.
In a rendering, the template element represents nothing.
The template contents of a template element are not children of the element itself.
<!doctype html>
<html lang="en">
<head>
<title>Homework</title>
<body>
<template id="template"><p>Smile!</p></template>
<script>
const fragment = document
.getElementById('template')
.content
.cloneNode(true);
document.body.appendChild(fragment);
</script>
</html>
A "Custom Element" defines a new HTML tag which will have all the properties of a native HTML tag
Such as: div, ul, p, a, etc.
The custom elements are the backbone of web components, and they are the ones that offer us all the goodies of the life cycle:
There are at least 3 ways of writing custom elements right now.
customElements.define
class LifeCycle2 extends HTMLElement {
static get observedAttributes() { return ['class']; }
constructor () {
super()
console.log('LifeCycle2 created')
}
connectedCallback () {
console.log('LifeCycle2 element added to page.');
}
disconnectedCallback () {
console.log('LifeCycle2 element removed from page..');
}
adoptedCallback () {
console.log('LifeCycle2 element moved to new page.');
}
attributeChangedCallback (attrName, oldValue, newValue) {
console.log('life-cycle element attribute Changed')
console.log('attrName', attrName)
console.log('oldValue', oldValue)
console.log('newValue', newValue)
}
}
customElements.define('life-cycle2', LifeCycle2);
customElements.define with ES5
function LifeCycleEs5 () {
let _ = Reflect.construct(HTMLElement, [], new.target)
console.log('life-cycle-es5 element created but not attached')
return _
}
LifeCycleEs5.prototype = Object.create(HTMLElement.prototype)
LifeCycleEs5.prototype.adoptedCallback = function () {
console.log('life-cycle-es5 element moved to new page.')
}
LifeCycleEs5.prototype.connectedCallback = function () {
console.log('life-cycle-es5 element attached')
}
LifeCycleEs5.prototype.disconnectedCallback = function () {
console.log('life-cycle-es5 element detached')
}
LifeCycleEs5.prototype.attributeChangedCallback = function (attrName, oldValue, newValue) {
console.log('life-cycle-es5 element attribute Changed')
console.log('attributes', attributes)
}
Object.defineProperties(LifeCycleEs5, {
observedAttributes: {
configurable: true,
get: function () { return ['class']; }
}
})
customElements.define('life-cycle-es5', LifeCycleEs5);
document.registerElement (deprecated)
var ComponentProto = Object.create(HTMLElement.prototype);
ComponentProto.createdCallback = function () {
console.log('life-cycle element created but not attached')
};
ComponentProto.attachedCallback = function () {
console.log('life-cycle element attached')
};
ComponentProto.detachedCallback = function () {
console.log('life-cycle element detached')
};
ComponentProto.attributeChangedCallback = function (attrName, oldValue, newValue) {
console.log('life-cycle element attribute Changed')
console.log('attrName', attrName)
console.log('oldValue', oldValue)
console.log('newValue', newValue)
};
document.registerElement('life-cycle', {
prototype: ComponentProto
});
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
const header = document.createElement('header');
const shadowRoot = header.attachShadow({mode: 'open'});
shadowRoot.innerHTML = '<h1>Hello Shadow DOM</h1>';
// attachShadow DOCS https://developer.mozilla.org/en-US/docs/Web/API/Element/attachShadow
https://developers.google.com/web/fundamentals/web-components/shadowdom
As its name describes it adds the ability to import an HTML document into another HTML document.
This is perfect for webcomponents as we can define our web components as a file document.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/webcomponentsjs/2.0.2/webcomponents-loader.js"></script>
<link rel="import" href="./giphy-element.html">
<link rel="import" href="./giphy-search.html">
</head>
<body>
<giphy-search api-key="NilCckKtrJq9lDxMICbF7SrJTAN2wABk"></giphy-search>
</body>
</html>
<script src="./component-builder.js"></script>
<template>
<style>
:host {
display: flex;
flex: auto;
height: 200px;
overflow: hidden;
}
:host ::slotted(img) {
width: auto;
max-height: 200px;
}
</style>
<div class="giphy-search__gif">
<slot></slot>
</div>
</template>
<script>
'use strict';
(function () {
const thisDoc = document.currentScript.ownerDocument;
const GiphyElement = {
src: {
get () {
return this.getAttribute('src') || ''
}
},
template: thisDoc.querySelector('template'),
render () {
return `<img src="${this.src}" />`
},
events: {},
observedAttributes () {
return ['src']
}
}
window.addEventListener('WebComponentsReady', function(e) {
CreateComponent('giphy-element', GiphyElement)
})
})()
</script>
@highercomve
Slides
https://slides.com/highercomve/web-components
Repo
https://github.com/highercomve/talk-web-components