Advanced Vue.js concepts: mixins, custom directives, filters, transitions, and state management

Vue.js is arguably one of the easiest and most minimalist JavaScript frameworks with which to get started. While we cannot downplay the current momentum and volume of developers adapting Vue.js, you will agree with me that there are very few tutorials that cover advanced concepts in Vue.

In this tutorial, we will talk about:

  • Vue.js mixins
  • Custom directives
  • Filters
  • Transitions (enter/leave)
  • State management
  • Server-side rendering

Note: Vue in this tutorial refers to Vue.js 2.x versions

Setting up our environment

To get started, and also to skip the process of configuring webpack for the compilation from ES6 to ES5, we will use Vue CLI. If you do not have the Vue CLI installed, install it!

sudo npm install -g vue-cli

Vue mixins

Mixins are chunks of code which we can reuse. Think of it as a way of adhering to the DRY principle. DRY is an acronym that stands for “Don’t Repeat Yourself”.

Mixins are a flexible way to distribute reusable functionalities for Vue components. A mixin object can contain any component options. When a component uses a mixin, all options in the mixin will be “mixed” into the component’s own options.

The easiest way to understand how Vue mixins work is to actually work with them. Consider two components: “A” and “B”. Both filter for users based on the date created in their lifecycle. The function which filters for users based on their creation date would appear in the two different components, causing you to repeat yourself.

As we’ve discussed, that’s bad. But there’s an easier way to filter for users based on the date created AND avoid being repetitive. Any guesses?

Vue mixins. Good guess.

Keep in mind that the more repetitive you are, the more prone you are to errors. Let’s write some code.

First, let’s create a new project by running:

#create a new project
vue init webpack mixins
#change into the new project
cd mixings
#install npm packages
npm install

Once we are done with the above code, let’s go ahead and edit our src/components/hello.vue to:

Let’s take a quick look at the code block above. In our template section, we have one H2 tag with the content inactive users. Next, we have an ul tag with a looped li tag which prints out the name and age of each user who is inactive.

Now take a look at the script section. Notice we have a normal Vue component instance. In our data section, we have two properties which are status, and an array called users.

In our methods section, we have two methods: get_active_or_inactive which gets all the active users based on our status and filter_by_date . This returns an array of users in ascending order based on the created_at property.

Finally, we have the computed section, that comprises one method called inactiveUsers which calls both the get_active_or_inactive and filter_by_date function.

We understand what our hello component now does, but we might still wonder what the goal is. The goal is to have two components, one that displays active users and one that displays inactive users. The two codes will have both the get_active_or_inactive method and also the filter_by_date method (which is repetitive).

So, we use Vue mixins to unify those repetitive functions.

Next, we’ll create a new component called Active.vue and place the following contents into it:

If we look at the Active component above, the main changes from are hello component are:

  • The status property in data changed from 0 to 1
  • The computed property changed from inactiveUsers to activeUsers

Let’s unify the repetitive code into a mixin. To do this, create a new directory called mixins in our src folder. Next, create a file called firstMixin.js into our src/mixins folder and paste in:

Notice that in the code snippet above, it is the same as a new Vue component. In fact, we only moved the methods part of our two components into this new component like structure.

We will then need to alter our components to use this mixin as seen below:

Looking at the two components above, the difference from the original components is:

  • we no longer have our methods in our component
  • we added an import of our mixin to the script
  • we declared our mixin in the mixins section of our components

Let us bring all of this together and see if it works. To do this, replace our app.vue file with:

The only difference with the above app.vue file from the original app.vue file is:

  • we have imported our active component and declared it in our components section
  • we have also rendered our active component to the browser

If we run the npm run dev command on our terminal, and browse to http://localhost:8080/ we should see the following:

Custom directives

Everyone has heard about directives. You most likely cannot build a feature rich app with Vue without using directives like v-if, v-for, v-show, etc.

In this section, we will learn how to build a custom directive called v-test. This function replaces the text given to it with base64 representation of its text.

Directives are tiny commands you can attach to DOM elements. They are prefixed with v- to let the library know you’re using a special bit of markup and to keep syntax consistent. They are typically useful if you need low-level access to an HTML element to control behavior.

First, create a new project by running:

#create a new project
vue init webpack customdirectives
#change into the new project
cd customdirectives
#install npm packages
npm install

Next, open our src/main.js file and add the following code just before our app is declared:

In the above directive, we have listened for the insert hook of the element which our directive is being attached to. We modify both the color and background style properties of the element. Next, we defined a function that decodes a string into base64 encoding, then we then change the HTML of the element into the result of our function.

While this may seem confusing because of the inserted hook we have used, where exactly did the inserted hook come from?

According to the Vue documentation, there are called “hook functions”, and are explained below:

  • bind: called only once, when the directive is first bound to the element. This is where you can do one-time setup work
  • inserted: called when the bound element has been inserted into its parent node (this only guarantees parent node presence, not necessarily in-document)
  • update: called after the containing component’s VNode has updated, but possibly before its children have updated. The directive’s value may or may not have changed, but you can skip unnecessary updates by comparing the binding’s current and old values (see below on hook arguments)
  • componentUpdated: called after the containing component’s VNode and the VNodes of its children have updated
  • unbind: called only once, when the directive is unbound from the element

Basically, the hook we call largely depends on the time and manner we want our action to take place. In this directive, we want it to take place after the element has been inserted into its parent node.

Our src/main.js should look this way:

Does the new directive work? Let’s find out.

Move into src/components/Hello.vue and use the v-test directive on an element, such that our component now looks like this:

In the code above, we have applied the v-test directive on the first H1 and H2 element in our template.

If we run our current code base, we should end up with the following screen:


A Vue filter is essentially a function that takes a value, processes it, and then returns the processed value.

Filters are usable in two places: mustache interpolations and v-bind expressions. Filters should be appended to the end of the JavaScript expression, denoted by the pipe (|) symbol.

We want to write a filter that will capitalize every first word of whatever string we put into it. If, for example, we want the string hi there to start with a capital H and T.

First, create a new project by running:

#create a new project
vue init webpack customfilters
#change into the new project
cd customfilters
#install npm packages
npm install

Next, let us open our src/main.js file and add the following code just before our app is declared:

    return str.toLowerCase().replace(/^\w|\s\w/g, function (letter) {
    return letter.toUpperCase();

In the Vue filter we have defined above, we first convert the entire string to lower case, then check the first letter of the entire string and check the first letter that have a space character before and replaces it applying. toUpperCase() method.

Our src/main.jsmain should look like this:

Next, we need to test our filter that it works as it should. To do this, open src/components/hello.vue file and replace it with:

What changed?

The value of msg in our data section. Also, we have applied the camel filter when displaying the msg value on our first h1 in our template.

If we run our code now, we should see:

Notice that the first letter of every word in our msg variable is capitalized.

Transitions (Enter/Leave)

Transitions are effects that can be applied when elements are inserted, updated, and removed from the DOM.

The simplest way to achieve transition effects on your page is through Vue’s <transition>component. The <transition> component is made globally acceptable by Vue, which means it can be used and accessed within any component.

Vue works by adding and removing classes on elements during the transition process.

There are six different class prefixes while dealing with transitions which are:

  • -enter: contain styles for when the element begins to appear at the scene
  • -leave: contain styles for when the elements begins to leave the scene
  • -enter-active: styles for when the transition is in place e.g transition seconds
  • -leave-active: styles for when the transition is getting out of place e.g transition seconds
  • -leave-to: This replaces -leave
  • -enter-to: This is the ending class for enter. It is applied when -enter is removed

All we need to do for us to use transitions nicely is to add a style using any of the prefixes to the name of our transition. For example, if we have a transition named test , we can use them like this:

.test-enter-active {
    transition: transform 3s;
    text-shadow:0px 5px 10px #fdff00;
.test-leave-active {
    transition: transform 3s;
    text-shadow:0px 5px 10px #a1a194;
.test-enter, .test-leave-to {
    transform: translateX(90%);
.test-enter-to, .test-leave {
    transform: translateX(-15%);

First, create a new project by running:

#create a new project
vue init webpack transitions
#change into the new project
cd transitions
#install npm packages
npm install

Next, replace our src/components/hello.vue with:

In the code block above, we wrapped our first h1 element with a transition called “test”. We also created a new input element, which is a button that toggles the status variable, forcing our element to enter the “leave” and “enter” states.

In our script section, we added a new variable called status which is false by default. Next in our mounted call, we set it to “true”.

If we run our code base, we should observe that it works as shown in the image below:

State management

When your Vue application grows bigger and consists of multiple components you might run into the problem of how to share data across the those components and make sure that components which are using the same data are always updated if data changes.

Large applications can often grow in complexity, due to multiple pieces of state scattered across many components and the interactions between them. To solve this problem, Vue offers vuex

What is Vuex?

According to the official documentation for Vuex, it is a state management pattern and library for VueJS applications. It serves as a centralized store for all the components in an application, with rules ensuring that the state can only get mutated in a predictable fashion.

Vuex uses a centralized state management by implementing the following core concepts:

  • State: An object containing the data
  • Getters: Used to access data from the state tree of the store
  • Mutations: Handler functions that perform modifications of data in the state tree
  • Actions: Functions that commit mutations. The main difference to Mutations is that Actions can contain asynchronous operations

Let’s put these theories into practice.

First, let’s create a new project by running:

#create a new project
vue init webpack statemanagement
#change into the new project
cd statemanagement
#install npm packages
npm install

Next, we will install the Vuex library:

npm install Vuex

Once Vuex is installed, let’s explore our state, actions, mutations, and getters for our sample application.

When we explained what a state was, we said it was an object which contains data. If we look at the code above, we can see it is an object which contains an array of users.

Look at our actions:

actions: {
  ADD_USER: function({ commit }, new_user) {
    commit("ADD_USER_MUTATION", new_user);
  DELETE_USER: function({ commit }, user_id) {
    commit("DELETE_USER_MUTATION", user_id);

In our actions section, we define two functions:

  • ADD_USER:This function further commits a mutation called ADD_USER_MUTATION with the new user object it has received as an argument which will add a new user to the list.
  • DELETE_USER: This function further commits a mutation called DELETE_USER_MUTATION with the user id it has received as an argument which will delete a user from the list.

We now move into our mutations:

mutations: {
  ADD_USER_MUTATION: function(state, new_user) {
  DELETE_USER_MUTATION: function(state, user_id) {

In the above code, we have our mutations, which directly alter the state of our store. Inspecting the code, we notice two functions:

  • ADD_USER_MUTATION: This mutation pushes a new user into our list of users
  • DELETE_USER_MUTATION: This mutation deletes an object from the array of users based on the id passed, which is the index of that object.

Now lets take a look at our getters:

getters: {
  users: state => {
    return state.users;

In our getters block, we define one function:

  • users: This getter returns all users in our store

Next, let’s merge the concepts together to create our Vuex store.

Create a new file in our src folder called store.js and place in:

That’s how easy it is to get a Vuex store set up. Now to move into using this store in our application.

To notify Vue about our central store, we need to pass in the store object to our Vue instance while creating it. To do that, replace the content of our src/main.js with:

If you look at the code above, you will notice the import of our store component, and passing it to our Vue component.

Let’s change the Hello component so we can interact with our store.

Now, replace the content of src/components/hello with:

In the code block above, you notice we have declared set of HTML elements, in which we can find:

  • A text input which holds a new user name.
  • A text input which holds a new user age.
  • A text input which holds a new user status.
  • A text input which holds a new user date created.
  • A button element, to which we have attached a function, that adds a new user.
  • UL tags, coupled with LI tags for displaying users alongside a delete button.

We are now done reviewing the HTML part of our component.

It’s important to review our methods and computed properties so we can see how we interact with Vuex.

Within our methods, we will notice two functions which are:

  • add_user: This method dispatches the current user object to the store action called ADD_USER
  • delete_user: This method receives a parameter and then dispatches the parameter to the store action called DELETE_USER

Moving into our computed properties, we have only one function called users. This function returns all the users in our store.

If we run our code-base, it should work as shown below:

Server-side rendering

One downside of Vue as a JavaScript framework is that the page isn’t viewable until the browser has executed the app’s JavaScript bundle.

This causes apps to render blank pages and in some, keep showing a preloader for an awfully long time. The Vue team sought to solve this issue and came up with Server-side rendering known as SSR. Luckily for us, there is detailed info on how to implement server-side rendering in Vue available here.


In this tutorial, we covered a lot of advanced techniques using Vue. We also learned about creating and using mixins to stop code repetition. Lastly, we learned about custom directives, filters, transitions, state management, and server-side rendering.

I hope whatever you learned here will go a long way to help in writing more productive Vue applications.

The code base to this tutorial is available in this public GitHub repo. Please download for educational purposes.

Plug: LogRocket, a DVR for web apps

LogRocket is a frontend logging tool that lets you replay problems as if they happened in your own browser. Instead of guessing why errors happen, or asking users for screenshots and log dumps, LogRocket lets you replay the session to quickly understand what went wrong. It works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store.

In addition to logging Redux actions and state, LogRocket records console logs, JavaScript errors, stacktraces, network requests/responses with headers + bodies, browser metadata, and custom logs. It also instruments the DOM to record the HTML and CSS on the page, recreating pixel-perfect videos of even the most complex single page apps.