12 Vue.js Best Practices for Pro Developers | by Matt Maribojoc | Better Programming | Medium
As VueJS continues to become more and more widespread, there are several best practices emerging and becoming standard.
For this piece, I included some tips from a few great resources.
Hopefully, these best practices can help you write better Vue.js code. Not only will that make all your fellow developers love you, but you’ll definitely thank yourself down the line for making your life easier.
OK, enough introduction. Let’s dive right in.
1. Always Use :key Inside v-for
Using the key attribute with the v-for
directive helps your application be constant and predictable whenever you want to manipulate the data.
This is necessary so Vue can track your component state as well as have a constant reference to your different elements. An example where keys are extremely useful is when using animations or Vue transitions.
Without keys, Vue will just try to make the DOM as efficient as possible. This may mean elements in the v-for
may appear out of order, or their behavior will be less predictable. If we have a unique key reference to each element, then we can better predict how exactly our Vue application will handle DOM manipulation.
<!-- BAD -->
<div v-for="product in products"></div>
<!-- GOOD! -->
<div v-for="product in products" :key="product.id"></div>
2. Use Kebab Case for Events
When it comes to emitting custom events, it’s always best to use kebab case. This is because in the parent component, that’s the same syntax we use to listen to that event.
So for consistency across our components, and to make your code more readable, stick to using kebab case in both places.
this.$emit('close-window')
// then in the parent
<popup-window @close-window='handleEvent()' />
3. Declare Props With camelCase, and Use Kebab Case in Templates
This best practice simply just follows the conventions for each language. In JavaScript, camelCase is the standard, and in HTML, it’s kebab case. Therefore, we use them accordingly.
Luckily, Vue.js converts between kebab case and camelCase for us so we don’t have to worry about anything besides actually declaring them.
<!-- BAD! -->
<PopupWindow titleText="hello world" />
props: { 'title-text': String }
<!-- GOOD! -->
<PopupWindow title-text="hello world" />
props: { titleText: String }
5. Don’t Use v-if With v-for Elements
It’s super tempting to want to use v-if
with v-for
in order to filter elements of an array.
<!-- BAD! -->
<div v-for="product in products" v-if="product.price < 500"></div>
The problem with this is that Vue.js prioritizes the v-for
directive over the v-if
directive. So under the hood, it loops through every element and then checks the v-if
conditional.
this.products.map(function (product) {
if (product.price < 500) {
return product;
}
});
This means that even if we only want to render a few elements from a list, we’ll have to loop through the entire array.
This is no good.
A smarter solution would be to iterate over a computed property. The above example would look something like this.
<div v-for="product in cheapProducts"></div>
computed: {
cheapProducts: () => {
return this.products.filter(function (product) {
return product.price < 100;
});
};
}
This is good for a few reasons.
- Rendering is much more efficient because we don’t loop over every item
- The filtered list will only be reevaluated when a dependency changes
- It helps separate our component logic from the template, making our component more readable
6. Validate Your Props With Good Definitions
This is arguably the most important best practice to follow.
Why is it important?
Well, it basically saves future you from current you. When designing a large-scale project, it’s easy to forget the exact format, type, and other conventions you used for a prop.
And if you’re in a larger dev team, your coworkers aren’t mind readers, so make it clear to them how to use your components.
So save everyone the hassle of having to painstakingly trace your component to determine a prop’s formatting, and please just write prop validations.
Check out this example from the Vue docs.
props: {
status: {
type: String,
required: true,
validator: function (value) {
return [
'syncing',
'synced',
'version-conflict',
'error'
].indexOf(value) !== -1
}
}
}
7. Use PascalCase or Kebab Case for Components
A common naming convention for components is to use PascalCase or kebab case. No matter which one you choose for your project, it’s most important that you stay consistent all the time.
PascalCase works best, in my opinion, because it is supported by most IDE autocomplete features.
# BAD
mycomponent.vue
myComponent.vue
Mycomponent.vue
# GOOD
MyComponent.vue
8. Base Components Should Be Prefixed Accordingly
Another naming convention is focused around naming base components — or components that are purely presentational and help set up common styles across your app.
According to the Vue style guide, base components are components that only contain:
- HTML elements
- Additional base components
- Third-party UI components
The best practice for naming these components is to give them the prefix Base
, V
, or App
. Once again, it’s all right to use either of these as long as you stay consistent throughout your project.
BaseButton.vue
BaseIcon.vue
BaseHeading.vue
The purpose of this naming convention is it keeps your base components alphabetically grouped in your file system. Also, by using a webpack import function, you can search for components matching your naming-convention pattern and automatically import all of them as globals in your Vue project.
9. Components Declared and Used Once Should Have the Prefix “The”
Similar to base components, single-instance components (used once per page and not accepting any props) have their own naming convention.
These components are specific to your app and are normally things like a header, sidebar, or footer.
There should only ever be one active instance of this component.
TheHeader.vue
TheFooter.vue
TheSidebar.vue
ThePopup.vue
10. Stay Consistent With Your Directive Shorthand
A common technique among Vue developers is to use shorthand for directives. For example:
@
is short forv-on
:
is short forv-bind
#
is short for[v-slot](https://learnvue.co/2019/12/using-component-slots-in-vuejs%e2%80%8a-%e2%80%8aan-overview/)
It’s great to use these shorthands in your Vue project. But to create some sort of convention across your project, you should either always use them or never use them. This will make your project more cohesive and readable.
11. Don’t Call a Method on “created” and “watch”
A common mistake Vue developers make (or maybe it was just me) is they unnecessarily call a method in created
and watch
. The thought behind this is we want to run the watch
hook as soon as a component is initialized.
// BAD!
created: () {
this.handleChange()
},
methods: {
handleChange() {
// stuff happens
}
},
watch () {
property() {
this.handleChange()
}
}
However, Vue has a built-in solution for this. It’s a property of Vue watchers that we often forget.
All we have to do is restructure our watcher a little bit and declare two properties:
-
handler (newVal, oldVal)
— this is our watcher method itself. -
immediate: true
— this makes our handler run when our instance is created.
// GOOD!
methods: {
handleChange() {
// stuff happens
}
},
watch () {
property {
immediate: true
handler() {
this.handleChange()
}
}
}
12. Template Expressions Should Only Have Basic JavaScript Expressions
It’s natural to want to add as much inline functionality into your templates as possible. But this makes our template less declarative and more complex. Meaning our template just gets extremely cluttered.
For this, let’s check out another example of normalizing a string from the Vue style guide. Look how confusing it is.
// BAD!
{
{
fullName
.split(' ')
.map(function (word) {
return word[0].toUpperCase() + word.slice(1);
})
.join(' ');
}
}
Basically, we want everything in our template to be intuitive as to what it’s displaying. To keep this, we should refactor complex expressions into appropriately named component options.
Another benefit of separating out complex expressions is it means these values can be reused.
// GOOD!
{{ normalizedFullName }}
// The complex expression has been moved to a computed property
computed: {
normalizedFullName: function () {
return this.fullName.split(' ').map(function (word) {
return word[0].toUpperCase() + word.slice(1)
}).join(' ')
}
}
Conclusion
And there you have it.
Those were 12 of the most common best practices that’ll make your Vue code more maintainable, readable, and more professional.
Hopefully these tips were useful to you (because they’re definitely things that I always want to remember).
If you want to jump-start your Vue.js development, I’ve put together a VueJS cheatsheet that I use all the time. It has the essential information I got tired of looking up, so I compiled it into a tidy little three-page PDF.