Tutorial

Integrate Web Components with Your Vue.js App

Published on September 25, 2017
author

Joshua Bemenderfer

Integrate Web Components with Your Vue.js App

Even though the Web Components spec and implementations may not be considered to be mature by all, there are still quite a few interesting components and projects out there that you might find useful for your own purposes. That being said, Vue still offers a huge amount over plain’ol web components. (In fact, you can even make Web Components with Vue.) Well, why not have the best of both worlds? It’s actually really straightforward to use Web Components in Vue. Conditionals, properties, and even event bindings just keep working just like you’d expect them to.

Preparation

(This guide assumes you’ve started a quick Vue.js project with vue-cli and the webpack-simple template.)

Let’s go ahead an create a simple web component that illustrates properties and events with as little code as possible…

Behold: The ticking paragraph! Basically, it’s a wrapper for a paragraph. You set its text content through the content attribute. Oh, and it emits a tick event every half second or so for some reason. Yes, I lack creativity and / or the capability to come up with anything practical. Moving on.

ticking-paragraph.html
<template id="x-ticking-paragraph">
  <style>
    p {
      color: #42b983;
    }
  </style>
  <p id="renderTarget">
  </p>
</template>

<script>
  const currentScript = document.currentScript;

  customElements.define('x-ticking-paragraph', class extends HTMLElement {
    static get observedAttributes() { return ['contents'] }

    constructor() {
      super();
      let shadowRoot = this.attachShadow({mode: 'open'});
      const template = currentScript.ownerDocument.querySelector('#x-ticking-paragraph');
      const instance = template.content.cloneNode(true);
      shadowRoot.appendChild(instance);

      this.contents = '';

      setInterval(() => {
        this.dispatchEvent(new Event('tick'));
      }, 500);
    }

    set contents(value) {
      this._contents = value;
      this.shadowRoot.getElementById('renderTarget').innerText = this._contents;
    }

    get contents() {
      return this._contents;
    }

    attributeChangedCallback(name, oldValue, newValue) {
      this[name] = newValue;
    }
  });
</script>

I know, I know. I’m using the old HTML-imports style of component here because it feels more elegant… for a more civilized age. Also it totally looks like a Vue Single File Component doesn’t it? (Vue was inspired in part by the original Web Components spec.)

I’m not going to explain it all here, rather, if you’d like to see how to create a more proper Web Component for Modern Times™, we’ve covered that too.

Alright, so now we need to load it into the page somehow. We’ll also grab a polyfill along the way so this works in more browsers than just Chrome.

ticking-paragraph.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Vue + Web Components</title>
    <!-- Web Components Polyfill -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/webcomponentsjs/1.0.13/webcomponents-lite.js"></script>
    <!-- Loading our component -->
    <link rel="import" href="./ticking-paragraph.html">
  </head>
  <body>
    <div id="app"></div>
    <script src="/dist/build.js"></script>
  </body>
</html>

Now that we’ve done all that, we can finally use our component in Vue as stated by the title directly following this paragraph.

Using Your Component In Vue

Really the only thing we have to do to make Vue work with this component is whitelist it in Vue.config.ignoredElements. This just tells Vue that the element / component comes from a source that Vue doesn’t know about, and keeps the compiler from complaining.

src/main.js
import Vue from 'vue';
import App from './App.vue';

Vue.config.ignoredElements = [
  'x-ticking-paragraph'
]

new Vue({
  el: '#app',
  render: h => h(App)
});

Now, use the component like any other! Reactivity stays intact!

src/App.vue
<template>
  <div id="app">
    <h1>Vue ❤ Web Components</h1>
    <x-ticking-paragraph :contents="paragraphContents" @tick="logTick"></x-ticking-paragraph>
  </div>
</template>

<script>
export default {
  data() {
    return {
      paragraphContents: `I'm data from Vue rendering in a Web Component!`
    }
  },

  methods: {
    logTick() {
      console.log(`The paragraph ticked again. >_>`)
    }
  }
}
</script>

The best part is, you don’t need to make any changes to the Web Component or to your Vue app to somehow force them to grudginly work together. It works right out of the box! In fact, you can even integrate elements that internally use other frameworks like Polymer or React.

Now, how useful this ends up being to you depends entirely on whether or not you are (or want to be) using Web Components alongside Vue. That said, if nothing else, it does indicate that if Web Components are the future, Vue is future-proof.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about our products

About the authors
Default avatar
Joshua Bemenderfer

author

While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
Leave a comment


This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

Become a contributor for community

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

DigitalOcean Documentation

Full documentation for every DigitalOcean product.

Resources for startups and SMBs

The Wave has everything you need to know about building a business, from raising funding to marketing your product.

Get our newsletter

Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.

New accounts only. By submitting your email you agree to our Privacy Policy

The developer cloud

Scale up as you grow — whether you're running one virtual machine or ten thousand.

Get started for free

Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

*This promotional offer applies to new accounts only.