I’ve been doing Vue for some time now.

Along the way, I’ve come across a lot of learnings, a lot of gotcha’s and a lot of yay moments.

As a result of this, I would like to share my advice, tips and best practices to you, if you’re in the moment of building a new Vue application. What you should do, what you should avoid, and generally just some plain old good advice 😉

New to Vue?

I’ll recommend that you learn Vue from the some of the best courses out there — I’ve provided some links to useful resources at the bottom of this article

Anyway, let’s get to it.

Install VueDevtools

Install VuePerformanceDevtool

When installed, you need to add this to your code:

Vue.config.performance = true;

Component Communication

<my-component :firstProp="someValue"></my-component>

This is just a one-way communication. If you want to inform your parent component that someValue has changed, you can use events.

export default {
methods: {
onClick() {
this.$emit('nameOfEvent', someValue);

You can in your parent component, react to the event you just emitted

<my-component :firstProp="someValue" @nameOfEvent=”doSomething”></my-component>

The built in $emit() method is only used when you need to have child/parent communication.

If you need more complex communication, you can use the EventBus (See this article: https://alligator.io/vuejs/global-event-bus/) or Vuex.
The EventBus is meant for smaller applications where you don’t have a lot of shared state across components. If you know your application is going to be complex, go with Vuex instead.

Use Vuex for state management

I remember the first Vue application I built — I started out using the EventBus, but that quickly became confusing and unmaintainable — And the refactoring was hell.

Vuex, Go learn it, and learn it good. Make use of it ASAP if you start to see your application grow — This is really a great addition when you need to scale your Vue application.

  • Get to know the concept of state, getters, mutations and actions
  • Look into Vuex modules
  • Learn how to create a good structure, as Vuex doesn’t give you any restrictions
  • Learn how the “strict” mode works
  • Add the Vuex Cheatsheet as a bookmark to your browser: https://github.com/vuejs-tips/vuex-cheatsheet

Additional resources on Vuex:


Code Splitting

const Loader = () => import(/* webpackChunkName: "aChunkName" */'../path/to/component.vue');

There are a few other patterns you can use — Check out this article from Anthone Gore: https://vuejsdevelopers.com/2017/07/03/vue-js-code-splitting-webpack/

Shortcut component registration

import MyAwesomeComponent from './my-awesome-component.vue';...
components: {
'my-awesome-component': MyAwesomeComponent

This is not wrong at all, but there is a nice little shorthand for doing this:

components: {

Shortcut for registering components globally

import ComponentA from './component-a.vue';
import ComponentB from './component-b.vue';
import ComponentC from './component-c.vue';

Vue.component('component-a', ComponentA);
Vue.component('component-b', ComponentB);
Vue.component('component-c', ComponentC);

If you have a lot of components this can get a tedious task. You can easily create a function that can handle the component registration for you.

Simply create an object with your components and loop through the object and do the registration

const ctors = {};

const components = {

//Attach component to vue globally - NOTE: Remember to define a name in your component...
Object.keys(components).forEach(function (key) {
const component_name = components[key].name;
if (component_name) {
ctors[component_name] = Vue.component(component_name, components[key]);
} else {
throw new Error('It seems you forgot go give your component a name...');

Avoid registering all components as global components

Specific components should be imported in other components, by using async components if possible. (Components in components)
This will keep your bundle size small and your application more performant. See the section about code splitting in this article.

Validate your props

Learn more about prop validation here: https://vuejs.org/v2/guide/components-props.html


NOTE: If you are using the VueCLI, you can add it to your application very easy, without having to install in manually through npm-install vue-router

Official docs here: https://router.vuejs.org/

URL changes, but view doesn’t update

This is most likely a result of using the same component, and Vue will then reuse the instance. The this.$route in the component will change but all lifecycle hooks like created(), beforeMounted() and mounted() hooks won’t be re-instantiated.
For this problem, there are a few solutions:

To force Vue to create a new component instance you can set a unique key in the <router-view>

<router-view :key="$route.fullPath">

Or setup a watch handler so you can react to a route change

watch: {
"$route.params.somevalue": {
handler(somevalue) {
// do stuff
immediate: true

You are (almost) forced to have a root node.

<div> <!-- The root -->

So by default you can’t do


This will return an error:
Component template should contain exactly one root element. If you are using v-if on multiple elements, use v-else-if to chain them instead.

There is a way to get around this by using functional components, which Anthony Gore has written a great article about: https://vuejsdevelopers.com/2018/09/11/vue-multiple-root-fragments/

Form Validation made easy

Get to know Vue’s lifecycle hooks.

I.e: you can’t access a property in your data if you are trying to access it when using the beforeCreated() hook, and you cant get a ref element in the created() hook as the template isn’t mounted to the DOM yet.

Avoid manipulating the DOM directly

Instead you should make use of $refs. This is a clean way of accessing the DOM, and the Vue way. It’s also more maintainable, as you won’t have to deal relying on elements with specific class names, ids etc…

Learn more about using $refs in this short video: https://www.youtube.com/watch?v=rSyFM2FANtk

Working with data


<div v-for="item in items" v-bind:key="item.id">
<!-- content -->

Always remember to add a :key to your list unless you have a very simple array. This is the recommended way as you can gain performance whenever Vue needs to update a components in your loop, as it is used as an identifier. If you provide duplicate keys, Vue will give you a warning in the console.

Learn more about keys here: https://vuejs.org/v2/api/#key

Computed properties vs Methods

names: ["Leonardo", "Donatello", "Rafael", "Michaelangelo"]
return this.names.filter(name => name.startsWith("D"))

<p v-for="(name, index) in startsWithD" :key="index">{{name}}</p>

A good rule of thumb. If you have complex computed properties, split them into many simple computed properties., this is easier to test, more maintainable and more readable.

A method is a function bound to the Vue instance. It will only be evaluated when you explicitly call the method, just like a regular javascript method.

names: ["Leonardo", "Donatello", "Rafael", "Michaelangelo"]
return this.startWithCharacter("D")
return this.startWithCharacter("L")
return this.names.filter(name => name.startsWith(char))

Learn more about computed properties here: https://vuejs.org/v2/guide/computed.html

Know the power of mixins

Learn more about mixins in the docs: https://vuejs.org/v2/guide/mixins.html

Know the power of filters

filters: {
formatDate: function (date) {
if(date) {
//format using date-fns
return format(
new Date(date),
} else {
return '--';

Lean more about creating filters here: https://scotch.io/tutorials/how-to-create-filters-in-vuejs-with-examples

Utilize the built in modifiers

Form modifiers / https://vuejs.org/v2/guide/forms.html#Modifiers

  • .lazy
  • .number
  • .trim

Event Modifiers / https://vuejs.org/v2/guide/events.html#Event-Modifiers

You probably caught yourself using event.preventDefault() a few times if you had to deal with submit / click events.
Vue provides us with a few event modifiers, so we don’t have to write that code ourselves:

  • .stop
  • .prevent
  • .capture
  • .self
  • .once
  • .passive

Key Modifiers

  • .enter
  • .tab
  • .delete
  • .esc
  • .space
  • .up
  • .down
  • .left
  • .right

Another cool thing is that you can define your own custom key modifiers by using the global config.keyCodes

Good structure!

Because of this flexibility it’s very much up to you, or your team to create a good and understandable structure that all team members can understand and work with.

I can’t stress out enough how important I personally think it is to think about how you are going to setup a good and meaningful structure. Changing it later becomes a hazzle… Trust me…. 😊

More tips on structuring for Vue application for large scale projects here: https://dev.to/maxpou/3-tips-for-scaling-large-vuejs-application-2edi

Clean up after yourself.

This could look something like:

created() {
refreshUserLoginTokenInterval(); //At created we start an interval to refresh
beforeDestroy () {
destroyUserLoginInterval(); //Before component is destroyed, we clean up

The Vue docs also holds some valuable information about avoiding memory leaks:

Add multiple classes to an element

//Add class red if isError is true
<div :class=”{'red': isError}”></div>

But how do you add multiple classes? There a few different approaches you can use, but the most common and easy is this:

// Add to classes if two properties return true
<div :class="{'red': isError, 'text-bold': isActive }”></div>

You can also add multiple classes based on a computed function — Here’s a great example on this: https://bytutorial.com/blogs/vuejs/how-to-bind-multiple-css-classes-in-vuejs

Pheeeew, you got all the way through. I could have written even more, but a person can only take in so much knowledge at a time 😊

Vue has a lot to offer and is a really great joy to work with, and even more fun if you know some of the best practices, gotchas and useful tools.

I hope you enjoyed the article, and are up for some additional articles on Vue in the future 😊

If you’d like to catch up with me sometime, follow me on Twitter | LinkedIn | Facebook or simply visit my portfolio website (That is however in Danish)

Vue.js Developers

Helping web professionals up their skill and knowledge of…

Sign up for Vue.js Developers Newsletter

By Vue.js Developers

A weekly publication with the best Vue.js news and articles. Take a look.

By signing up, you will create a Medium account if you don’t already have one. Review our Privacy Policy for more information about our privacy practices.

Check your inbox
Medium sent you an email at to complete your subscription.

Nicky Christensen

Written by

Head of development @ AccuRanker— VueJS Fanboy — In love with most frontend related stuf — nickychristensen.dk / https://twitter.com/nickycdk

Vue.js Developers

Helping web professionals up their skill and knowledge of Vue.js

Nicky Christensen

Written by

Head of development @ AccuRanker— VueJS Fanboy — In love with most frontend related stuf — nickychristensen.dk / https://twitter.com/nickycdk

Vue.js Developers

Helping web professionals up their skill and knowledge of Vue.js

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface.

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox.

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic.

Get the Medium app