Vue vs Vanilla
Components for the Web

Johannes Kissel & Michael Müller

Accento Logo
Johannes Kissel

Johannes Kissel

Software Developer
at Disy Logo
in Karlsruhe

Enthusiastic about …

  • 🔗 The Open Web
  • 🚲 Cycling
  • 🎶 Singing
Michael Müller

Michael Müller

Full Stack Developer
at Echobot Logo
in Karlsruhe

Enthusiastic about …

  • 💻 Web Development
  • 🎶 Singing
  • 🍳 Cooking

Cadenza is big …

Cadenza sreenshot showing a map

… and it's legacy, but …

… not that kind of legacy …

Dung Heap
Dung heap, © Superbass / CC-BY-SA-3.0 (via Wikimedia Commons)

… or that kind:

Jenga Tower
Jenga tower, © Marco Verch / CC-BY-2.0 (via Flickr)

It's vivid and
constantly improved and extended

Frankfurt main station, © Urmelbeauftragter / CC-BY-SA-3.0 (via Wikimedia Commons)

How to be future proof?

Refactoring on the go demands
maximum interoperability

                            const ELEMENT_NAME = 'd-toggle-button';

                            class ToggleButton extends HTMLElement {
                              connectedCallback () {
                                this.setAttribute('role', 'button');
                                this.addEventListener('click', () => {
                                  this.pressed = !this.pressed;
                                  this.dispatchEvent(new CustomEvent('toggle', {bubbles: true}));
                              set pressed (value) {
                                this.setAttribute('aria-pressed', value);
                              get pressed () {
                                return this.getAttribute('aria-pressed') === 'true';

                            customElements.define(ELEMENT_NAME, ToggleButton);

Usage with Plain DOM

                            const button = document.createElement('d-toggle-button');
                            button.textContent = 'Button';
                            button.pressed = true;
                            button.addEventListener('toggle', () => {

Usage with Constructor

                            import ToggleButton from 'ui/toggle-button';
                            // or
                            const ToggleButton = customElements.get('d-toggle-button');

                            // Constructor
                            const button = new ToggleButton();

Usage with jQuery

                            const $button = $('<d-toggle-button>')
                              .prop('pressed', true)
                              .on('toggle', () => console.log($button.prop('pressed')))

Usage with Vue

                            new Vue({
                              el: '#app',
                              template: `<d-toggle-button
                              data: { pressed: true },
                              methods: {
                                onToggle: event => console.log(

Web Components

The Holy Grail

Web Components

The Holy Grail

A solid foundation
with the right level of abstraction

Railroad ties, © Störfix / CC-BY-SA-3.0 (via Wikimedia Commons)

A software component is a
unit of composition with contractually specified interfaces and explicit context dependencies only.

The effect is HUGE!

Arrow pointing from the Grunt logo to the Webpack logo, indicating the transition from one tool to the other.


UI components have a name and can be reused.

Design Tools: Style Guide

Screenshot of the Disy style guide


Design Tools: Component library

Screenshot of the Disy component library


Web Components

  • Custom Elements
  • Shadow DOM
  • HTML Templates

Custom elements

                            class MyComponent extends HTMLElement {

                            customElements.define('d-my-component', MyComponent);

(Google primer on custom elements)

Custom Elements: Extending Built-ins

                            class MyButton extends HTMLButtonElement {

                            customElements.define('d-my-button', MyComponent, {extends: 'button'});

                            // Usage:
                            document.createElement('button', {is: 'd-my-button'});
                            // or
                            // new MyButton();
                            // <button is="d-my-button">My Button</button>

Custom Elements: Browser Support

Data on support for the custom-elementsv1 feature across the major browsers from

Custom Elements: Polyfilling

                              if (window.customElements) {
                                // Make the browser work with transpiled custom elements.
                                document.write('<script src="native-shim.js"></script>');
                              } else {
                                // Polyfill custom elements.
                                document.write('<script src="custom-elements.min.js"></script>');

Polyfill for Custom Elements

⇒ We look forward to extend built-in elements in the future.

Custom Elements: Lifecycle Callbacks

                            class MyComponent extends HTMLElement {
                              constructor () {
                                // Called when the element is created or upgraded.
                                super(); // Don't forget to call super().
                              connectedCallback () {
                                // Called when the element is connected to the DOM.
                              disconnectedCallback () {
                                // Complement to the connectedCallback()

Custom Elements: Attributes

                            class MyComponent extends HTMLElement {
                              static get observedAttributes() {
                                return ['some-attribute']; // Return attribute names to observe.
                              attributeChangedCallback (name, oldValue, newValue) {
                                // Called when the observed attributes' values change.

Custom Elements: Properties

                            class ToggleButton extends HTMLElement {
                              connectedCallback () {
                                this.addEventListener('click', () => {
                                  this.pressed = !this.pressed;
                                  this.dispatchEvent(new CustomEvent('toggle', {bubbles: true}));
                              set pressed (value) {
                                this.setAttribute('aria-pressed', value);
                              get pressed () {
                                return this.getAttribute('aria-pressed') === 'true';

Shadow DOM

                            class Tabs extends HTMLElement {
                              constructor() {

                                const shadowRoot = this.attachShadow({mode: 'open'});
                                shadowRoot.innerHTML = `
                                  <style>#tabs { border-bottom: 1px solid; }</style>
                                  <div id="tabs">
                                    <slot name="tabs" />
                                  <div id="panels">
                                    <slot />
  • Scoped Styles
  • Declarative Composition (Google primer)

Shadow DOM: Browser Support

Data on support for the shadowdomv1 feature across the major browsers from

Polyfill for the Shadow DOM

Shadow DOM: "Challenges"

  • Polyfills are "shady" and horribly slow.
  • Scoped styles require native CSS custom
    properties to be really useful.
  • No server-side rendering (although people try)

⇒ We do not use the Shadow DOM and do not recommend it.

HTML Templates

                            <ul id="todoList"></ul>
                            <template id="todoTemplate">
                                  <input type="checkbox"> <span class="text"></span>

                            const todos = document.querySelector('#todoList');
                            const template = document.querySelector('#todoTemplate');
                            template.content.querySelector('.text').textContent = 'Give a talk';
                            template.content.querySelector('input').checked = true;
                            todos.append(document.importNode(template.content, true));

HTML Templates: Browser Support

Data on support for the template feature across the major browsers from

Polyfill for HTML Templates

⇒ HTML Templates work nicely, but we don't use them, yet.

And did I mention…

  • 🔋 Batteries included
  • 🎓 Flat learning curve
  • 🛠️ Great devtools
  • ️ You can use <x> with Web Components
  • 📈 Big companies do commitments

Bottom line

  • We have three years of experience with Custom Elements.
  • Recently, we replaced our last RichFaces component.
  • We benefit a lot and we'll move on into that direction.

Keep calm and #UseThePlatform

Departing train, © Xenotron / CC BY 4.0 (via Wikimedia Commons)

  • ~100 Servers
  • 4 Developers
  • every project has one responsible person
  • goal is uniform technology landscape
  • Name: DATACARE
  • Cleaning and enrichment of company data
  • Prototype ready for DMEXCO exhibition

There was only one problem…


Analyzing JS frameworks

  • Angular is too heavy weighted
  • WTF is a Web Component?!
  • I knew Vue.js from an internal project

The technologies we agreed on

  • Vue Logo
  • TypeScript Logo
  • Element UI Logo

What is Vue.js?

  • pronounced like "view"
  • created in 2014 by Evan You
  • started as a side project when he worked for Google*
  • component centric
  • jquery.min.js: 84,8 KB | vue.min.js: 85,6 KB
*this "side project" has now more Github stars than React :)
Todo example

Project setup

Option #1

Option #2

                                    npm install -g @vue/cli

It get's better…

Single File Components

  • all the parts that belong together in one file
  • need some time getting used to but make total sense
  • SFCs are opt-in
  • JSX is also possible
  • if your SFC gets too big: create a subcomponent!






                            import Vue from "vue";
                            import HelloWorld from "./HelloWorld.vue";

                            Vue.component("hello-world", HelloWorld);

                            new Vue({
                              el: "#app",
                              template: ""

How to structure a Vue app?

What I ️ about Vue

  • ☯️ Simplicity
  • 📖 Vue documentation
  • 🚀 Vue ecosystem
    • vue-router
    • vue-i18n
    • Nuxt.js

Bottom line

  • The prototype got finished in time.
  • After 6 months my boss was finally convinced.
  • New Vue projects are spreading.

Keep calm and #becomeaddicted

© Ryoji Iwata via

How to convince YOUR boss?


Build something with it


Collect arguments


Sit back and relax