Web-Components with Vuejs

Pointed as an alternative to develop web applications, Vuejs is a framework which focuses on the view layer, helping the development of applications based on components.

In this post I’ll show you the power of this tool.

Before talking about it, some concepts must be made clear. It’s necessary to understand why this framework was created, what problems it solves, and where it’s useful.

MVC is an acronym to Model-View-Controller, which is a software architectural pattern that splits your application into three layers: View (user interaction layer), Model (data manipulation layer) and Controller (application control layer).

This pattern has been used by many teams and companies, no matter what type, language or size of the project. Some popular frameworks were built following this architecture. Angularjs, created by Google team in 2010, is an example.

CBA is an acronym to Component-Based-Architecture. It takes small parts of the interfaces as independent components and reuses it inside other systems. Things will be clearer if you imagine a component as a resource that is part of the interface.

Components need to:

  1. Be independent.
  2. Interact with other components at the same space, without affecting them.
  3. Have their own structure, methods, and APIs.
  4. Be reusable and “plugged” in any place of the application.

A good example of a framework based on components is React. It was created by Facebook in 2013, following this “new approach” to web development.

After introducing you to component-based architecture, you need to understand one more concept, according to which every application has a state and it’s through it that we access the information that will be read and/or edited. Every component has its own state or just reads the state of another component.

That is when you need to be introduced to the concepts of stateful and stateless components.

Stateful

A stateful component has information about the state of the application and can edit it, predicting what changes may or will occur.

const hour = 21;

const increment = () => hour + 1;

increment(); // 22

See that the increment function has access to a state out of its own scope. It’s a characteristic of a stateful code.

Stateless

On the other hand, a stateless component hasn’t got information about the state itself and can’t change it. A certain input is always expected to have the same output. Translating it into code:

const hour = 21;

const increment = (x) => x + 1;

increment(hour); // 22

Notice that now, the increment function receives a state as a parameter and does not change anything out of its own scope. It’s a stateless code.

All these concepts and terms are related to Web Components. Basically, the web components are a collection of APIs that allow you to create new reusable and fully-customized HTML tags.

To work with web components, it’s necessary to understand their specifications, which are divided into Custom Elements, HTML Imports, HTML Templates and Shadow DOM. The purpose of this post isn’t to discuss Web Components, but if you are interested on the topic, take a look at the documentation.

Some of the most recent frameworks widely use two specifications: Custom Elements, which allow you create new DOM elements and Shadow DOM, which defines how you encapsulate style and markup into the component.

Working with modules allow us to divide the code into little parts, providing better management and organization, so all you have to do is basically import and export something.

Exporting one module:

export default function bar() {
  console.log("Hi, bar");
}

Importing and using my module:

import bar from "./bar";

bar();

Basically, you can export a module inside the bar.js file and use it inside another app.js file.

Unfortunately, not all the browsers don’t recognize modules like this yet, so it’s necessary to use tools such as Webpack or Browserify, called module bundle. They take all modules and put them into just all modules and putting them into just one file that the browsers can understand.

Now you are familiar with the concepts, it’s time to start coding with Vue!

So as in other frameworks, it is possible to start the development in two ways: via Content Delivery Network (CDN) or Command Line Interface (CLI).

CDN

Using CDN, all you need to do is to add the script into the HTML file and initialize a new Vue instance assigning an object as its arguments. Notice that nothing else is necessary to write your first Hello World.

Hello world using CDN:

<html>
  <head>
    ...
  </head>

  <body>
    <div id="app">
      <h1>{{ message }}</h1>
    </div>

    <script src="https://unpkg.com/vue"></script>
  </body>
</html>

<script>
  new Vue({
    el: "#app",
    data: {
      message: "Hello Vue!",
    },
  });
</script>

CLI

$ npm install -g vue-cli
$ vue init webpack my-project

If you prefer to use CLI, there will be a basic structure to start the development following some templates. What templates are these? webpack, webpack-simple, browserify and browserify-simple. The first decision you will have to make is which module bundle to use, webpack or browserify. After this, you will have to decide which are the requirements the project needs.

By using templates without the suffix -simple, you will have a more complete structure, with pre-configured loaders, test environment to e2e and unit, routes, ESLint and other more advanced resources. Otherwise, if you don’t need these requirements to start the project, do for the options with -simple.

Now, we are going to explain how the components in Vue are built.

Globals

Vue.component(tagName, options);

Global components will be available in all the application, and its notation is described above. The first parameter tagName accept a string that contains the HTML tag. The second parameter accepts an object of options to the component.

The example of one global component:

Vue.component("my-component", {
  template: "<h1>Hello World!</h1>",
});

new Vue({
  el: "#app",
});

How do I use my component?

<div id="app">
  <my-component></my-component>
</div>

Single-File

Single-file components (or just SFC) is a different approach to creating components and it’s the main difference from Vue to other frameworks.

How does a SFC work?

  • The file extension needs to be .vue
  • One single-file component has: markup (HTML), style (CSS) and behavior (JS)
  • It allows you to work with any markup language
  • It allows you work with pre and/or post-processors
  • It adds scope to your CSS

What would this file look like?

<template>
  <h1>{{ message }}</h1>
</template>

<script>
  export default {
    name: "My Component",
    data() {
      return {
        message: "Hello World",
      };
    },
  };
</script>

<style scoped>
  h1 {
    color: red;
    font-size: 16px;
  }
</style>

After giving you a general idea about the structure and how the component works, let’s go down to the dark side.

The data are the most basic part of the component, being responsible for its state, and it should be a function that returns an object. You just need to use the famous {{ }} inside your template to bind it.

<template>
  <p>{{ isActive }}</p>
</template>

<script>
  export default {
    data() {
      return {
        isActive: false,
      };
    },
  };
</script>

The component’s lifecycle is important to get a better control of some actions or when you want to do something at a specific moment. To access a specific lifecycle, just call the cycle’s equivalent function.

export default {
  created() {
    console.warn("When the component was created.");
  },

  mounted() {
    console.warn("When the component was mounted.");
  },

  updated() {
    console.warn("When the component was updated.");
  },

  destroyed() {
    console.warn("When the component was destroyed.");
  },
};

To understand with more details and see the complete lifecycle list, check the documentation. A good exercise to improve the lifecycle concept is calling all functions just with console.log to visualize each step.

Props are used in communication between parent components and child components. They need to be an object that allows validation by informing whether is it required and its expected type.

<template>
  <div>
    <h4>{{ address }}</h4>
  </div>
</template>

<script>
  export default {
    props: {
      address: {
        type: String,
        required: true,
      },
    },
    data() {
      return {
        address: "",
      };
    },
  };
</script>

<style></style>

If you have any question about how to use props, check the documentation.

As in many frameworks, Vue has directives and their application works similarly to other frameworks’ ones. Some directives are more famous than others, as v-model, v-on, v-bind, v-for, v-show, v-if. Some directives can be registered using the shorthand version, which would be a more declarative way to write the directive.

<button v-on:click="doSomething">Click</button>

<button @click="doSomething">Click</button>
<a v-bind:href="url" v-bind:class="myClass"> link </a>

<a :href="url" :class="myClass"> link </a>

You can also create new directives. To more details, check the documentation.

The methods are an object of functions that make up the component. If the component has any click, or another function is called from an event, it will be put on methods object.

<template>
  <button @click="toggle">Change Status</button>

  <p>{{ active }}</p>
</template>

<script>
  export default {
    name: "Toggle button",
    data() {
      return {
        active: false,
      };
    },
    methods: {
      toggle() {
        this.active = !this.active;
      },
    },
  };
</script>

For more details about methods, the documentation can help you.

Vue has another specific characteristic that is called modifier, which works as a special notation that attaches a different behavior to a certain element. We have a common example below in which preventDefault() is used in the submit event of the form to cancel the form’s default action, which is submitting the page.

<form id="myForm"></form>
  <script>
    let myForm = document.getElementById('myForm');

    myForm.addEventListener('submit', doSomething, false);

    function doSomething(e) {
      e.preventDefault();
    }
  </script>

Vue has its own special syntax to work with this sort of case.

<form @submit.prevent="doSomething"></form>

There are useful modifiers to keys, events, forms and directives. To more details, check the documentation.

Tests are an interesting subject to discuss, mainly because of different types, integrations and frameworks, for example. We will focus on two types of tests: unit and end-to-end. For more details about each type of test or what they are used for, I suggestion you to read this material that explains each of them.

Unit tests

Vue allows you to use Jasmine as a test framework and Karma to run them. Both are amongst the most used by the community.

<template>
  <span>{{ message }}</span>
</template>

<script>
  export default {
    data() {
      return {
        message: "Hello!",
      };
    },
    created() {
      this.message = "Bye!";
    },
  };
</script>
import Vue from "vue";
import MyComponent from "@/MyComponent.vue";

describe("MyComponent Spec", () => {
  it("Sets the correct default data", () => {
    const cpData = MyComponent.data();
    expect(cpData.message).toBe("Hello!");
  });
});

End-to-End (e2e)

Vue allows you to use the Nightwatch as an e2e framework, being one of the most used by the Nodejs community. The tool is very simple and works with an intuitive code.

<template>
  <div id="app">
    <h1>{{message}}</h1>
  </div>
</template>

<script>
  export default {
    data() {
      return {
        message: "Hello World!",
      };
    },
  };
</script>
const devServer = browser.globals.devServerURL;

browser
  .url(devServer)
  .waitForElementVisible("#app", 5000)
  .assert.containsText("h1", "Hello World!")
  .end();

If you were wondering about hybrid and/or desktop apps, it’s time! You can also use Vue to build desktop or hybrid apps. Some alternatives available on Github are:

Every framework has a community behind it — people who work together with other members to enhance to the tool. What’s the Vue community doing?

i18n

The documentation is available in some languages as: Japanese, Chinese, American English, Korean, Russian and Brazilian Portuguese (under development).

Debug

To help the developers, Vue has a tool for the debugger. Just download the browser extension and you will have more information about its components, the props, the state flow, the actions and the commits present in the application.

Awesome List

Probably you have already heard of the awesome-lists, and Vue also has a list where you can find podcasts, tutorials, components, utilities, examples, apps, websites and companies that are using Vue in their production or in their own experiments.

Slack

If you would like to participate in group discussions about the framework or have any questions, I recommend using Slack to build a network that can help you solve your problems and allow you to interact with the Brazilian community.

Email

Do you prefer to receive information in your inbox? A newsletter is a good option to keep updated about the technology world.

Forum

It’s normal for developers to use the stack overflow, right? Vue has a forum with thousands of questions, and you can find the solution to your problem more quickly there.

Articles

The Brazilian community of Vuejs is very active, always posting high quality content about coding or about the framework.

If your project needs:

This tool is useful to small projects or big projects, SPA or not.

This post doesn’t address everything the tool is used for, it just gives a general overview of some topics with examples. I hope that you have questions about what I said here and search for more about this awesome tool.

I invite you to see the code and slides of this project, in which I’m using the concepts covered throughout of the post.

This post used the links below as reference. If you want to know more about this tool, please check these materials: