If you want to become a master of your craft you’ll need to learn from the best. For those developers that are trying to become Vue masters, what is a pro-tip that you’ve learned that’s really helped you?
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. For me, this talk, plus going through all the official Vue.js documentation before doing any code helped me a lot when it comes to architecture a new feature or a new application with Vue.js.
If you are completely new to Vue, this article will most likely not provide you any great value, as you need to have some basic knowledge in Vue to understand some of the things I’m covering in this post.
Anyway, let’s get to it.
When working with Vue, it’s impossible to live without VueDevtools. This is a Chrome/Firefox extension you can install, which makes debugging your Vue application a breeze — Github
This Chrome extension allows you to inspect the performance of Vue Components — A good and useful tool: Chrome
When installed, you need to add this to your code:
Vue.config.performance = true;
Components can communicate in different ways in Vue. You can use props to pass down data to your components
<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.
Use Vuex if you are going to build a medium/large application. When having a data heavy application and need to share and manage state across your application, use Vuex.
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.
Additional resources on Vuex:
https://vuex.vuejs.org/
https://vuejsdevelopers.com/2017/05/15/vue-js-what-is-vuex/
Performance is a big topic these days, and with applications getting larger and more complex, we need to make our applications as fast as possible. If you can, utilize code splitting. This is a great way of reducing your main javascript bundle size, and thereby improve the initial load of your application.
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: here/
When working in components, we might need to import other components. I’ve seen many times where components gets registered like this:
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: {
MyAwesomeComponent,
MyAwesomeComponentTwo,
MyAwesomeComponentThree
}
A tip that’s worked well with me to really understand things involved always starting small/simple before building up on certain topics.
When registering components globally, the common pattern is that we import our component and then use vue.component() to register it.
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 = {
ComponentA,
ComponentB,
ComponentC
};
//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...');
}
});
Global components should only be used for base components which you use all time in your application.
This could be components such as a Buttons/Inputs etc.
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.
When passing props to a component, you should IMHO always do some validation. If you pass props without defining which type it should be (String, Array, Object……), it can be very hard for other team members to know what to pass.
Learn more about prop validation: here
When building a SPA application, you most likely need client-side routing. Vue doesn’t ship with built-in routing. Vue however does have an official plugin you can make use of — VueRouter. It’s super simple to work with and provides all the functionality you need to create a powerful application.
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/
When working in a SPA, you will most likely be reusing component in views. Imagine you’re on a blog post, and from there go to another blogpost, you would expect the content to change to the new content, but it doesn’t.
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 :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
}
}
By default, each component in Vue needs to have a single root node. This can unfortunately lead to some headaches, as we don’t necessarily always want to have a wrapping div in our components:
<template>
<div> <!-- The root -->
<span></span>
<span></span>
</div>
</template>
So by default you can’t do
<template>
<span></span>
<span></span>
</template>
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.
We all know that building form validation from scratch can be somewhat cumbersome, and very time consuming.
Luckily, there is a few great form validation plugins for Vue out there. I definitely recommend that you take a look a either Vuelidate or VeeValidate. Both are great and will save you a lot of time when working with forms.
To utilize the power of Vue, I strongly recommend that you get to know the lifecycle hooks.
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.
A good rule of thumb when working with Vue, is that you should by all means avoid accessing the DOM directly.
One of the main purposes with a javascript framework like Vue is to avoid messing directly with the DOM, like you would do with Vanilla JS or jQuery.
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
Every application most likely needs to communicate with some sort of external service at some point, either to fetch/post data.
For simple operations, and depending on which browsers you need to support, using the native fetch() method might be enough.
If not, I recommend you use the axios npm package. It’s one of the most popular packages, and is widely adopted by the React / Vue community.
We can easily loop through an array of objects with v-for
<div v-for="item in items" v-bind:key="item.id">
<!-- content -->
</div>
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
Computed properties are the goto when you want to manipulate data that exists in your Vue instance — another bonus that they are really performant as they are also cached from their reactive dependencies.
data:{
names: ["Leonardo", "Donatello", "Rafael", "Michaelangelo"]
},
computed:{
startsWithD(){
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.
data:{
names: ["Leonardo", "Donatello", "Rafael", "Michaelangelo"]
},
computed:{
startsWithD(){
return this.startWithCharacter("D")
},
startsWithL(){
return this.startWithCharacter("L")
}
},
methods:{
startWithCharacter(char){
return this.names.filter(name => name.startsWith(char))
}
}
Learn more about computed properties: here
When we are building our applications, we often need to reuse functionality across across components. Mixins are a great way to do this. This means if I create a component that holds X different methods/lifecycle hooks/local state etc, I can create a mixin and make other extend this mixin, making the methods and what not available in our new component.
Learn more about mixins in the: docs
Filters are great, especially when you are dealing with date-formatting, currencies etc. Filters enables you to create global or local formatting functions which you can use. Widely inspired by AngularJs
filters: {
formatDate: function (date) {
if(date) {
//format using date-fns
return format(
new Date(date),
'DD.MM.YYYY'
)
} else {
return '--';
}
}
}
A real cool feature in Vue, is the built-in modifiers. There are different modifiers which you can use in different scenarios. I urge you to learn and utilize these. Get to know them and it will save you a lot of time when writing your code.
In this article, I won’t go into detail on how you can use them, as the documentation of Vue describes this in great detail
Form modifiers / here
Event Modifiers / here
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:
Key Modifiers
Another cool thing is that you can define your own custom key modifiers by using the global config.keyCodes
Vue doesn’t come with any default way of structuring your application (Unless you are using Nuxt), which can be good, but can also become very messy if you aren’t an organized person.
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…
If you are building a SPA you can build up memory usage and if you don’t remember to remove custom events, instances, intervals, etc, eventually your application will become slow and unresponsive.
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:
here
You may also like: Keeping your Vue.js code Clean.
This is something I find myself doing a lot. Luckily Vue makes it very easy to add a dynamic class 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
Learn how Vue.js gets it’s Reactivity in this free lesson.
If you’re beyond the Vue basics, we hope that you’ve found pro tips from this post. I hope you enjoyed the article, and are up for some additional articles on Vue in the future.
Don’t forget to share it before leaving! Thank you so much!
#Vuejs #vue #vuex #javascript #Front End Development