Sergio Marin

@highercomve

Who is talking?

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

When you hear components do you think about?

Why not?

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.

More on that ...

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.

Web Components

What is a component?
Do we use them now?

Reusable component
Eric Raymond’s 17 Unix Rules

Lets resume 17 rules on 7 rules

  • Modularity
  • Clarity
  • Composition
  • Separation
  • Simplicity
  • Representation
  • Extensible

Web Components

are the future

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.

What do these frameworks offer us?

  • Abstraction of the DOM
  • Component Life Cycle
  • Community
  • Data binding
  • Routing ...? (maybe...)

Did you know web components are native supported by the Browser?

Current Support

HTML Template

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.

HTML Template

<!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>

Custom Element

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.

Custom Element

The custom elements are the backbone of web components, and they are the ones that offer us all the goodies of the life cycle: 

 

  • On creation event
  • On mounted event
  • On props change event
  • On destruction event

 

There are at least 3 ways of writing custom elements right now.

Custom Element

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);

Custom Element

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);

Custom Element

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

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

Shadow DOM

 

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

Shadow DOM

 

HTML Imports

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.

HTML Imports

<!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>

HTML Imports

<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>

Demo Time!

Thanks!

Twitter

@highercomve

 

Slides

https://slides.com/highercomve/web-components


Repo
https://github.com/highercomve/talk-web-components

Back to the browser - web components

By Sergio Marin

Back to the browser - web components

  • 804