Clean up after yourself

Most of the times we use Vue with third-party plugins. Let’s say we want to mount a color picker library into our component. That usually means, we have to import the module and initialize it in the mounted() hook. It might look like this.

mounted() {
this.colorPicker = ColorPicker({
el: this.$refs.colorPicker,
onUpdate: this.updateHexValue

The mounted hook gets called when our component root element (accessible as this.$el) has been mounted to DOM. After that, we are able to access our referenced elements and manipulate them or, as in this instance, use them to initialize a color picker.

The gotcha with this is that after our component is destroyed, the ColorPicker instance is not. At least not properly. The reference to it is lost and hopefully garbage-collected, but since the time it was created, ColorPicker might have attached a few event listeners in our DOM which still exist.

All well-written libraries should provide an API method to destroy their initialized instances and clean up after themselves. We should check the documentation and confirm the library includes a method that does it. If it doesn’t, it’s time to find a different library.

All we need to do next is call this method in the beforeDestroy() hook.

beforeDestroy () {

To demonstrate this problem, I created a fiddle:
Each component you add creates an event listener but doesn’t remove it.
Create a bunch, remove them and click anywhere in the window to see what’s happening.

The :key to success

If you’ve used Vue before you’ve most likely encountered this warning message

component lists rendered with v-for should have explicit keys

Why do we need to pass a key to v-for elements? To cite the documentation

Why is this important? Because things can go wrong if we use “index” as the key.

<div v-for="(user, index) in users" :key="index">
{{ }}

After we shuffle the order of our array, the indices will always remain the same (0, 1, 2, 3…) which really doesn’t affect us in this case if we are only displaying the user name.

However, there are cases when problems arise. Let’s try adding a text input.

<div v-for="(user, index) in users" :key="index">
{{ }}
<input type="text"/>

When we shuffle the array of users now, the user names will get updated as they should but the inputs will stay in their original positions with the same values.

To solve this problem, we would pass a unique id to the key directive to tell Vue that we want to track our elements not by indices, but by ids. In order for this solution to work, we assume that our user objects contain an id property.

<div v-for="(user, index) in users" :key="">
{{ }}
<input type="text"/>

If you want to see the difference using index vs unique id as the key, check this fiddle

Using keys with transitions

I have often encountered a scenario when using the transition component for animations that use the same tag name.

I remember the first time I was confused as to why my transition was not working:

<transition name="fade">
<p v-if="step === 0">Start now</p>
<p v-else-if="step === 1">Step 1</p>
<p v-else-if="step === 2">Step 2</p>

After some googling, I found out why. As stated in the documentation:

Try out the animations here

(Non)Reactive Data

All properties returned from the data() function are reactive by default. That means any time a piece of that data changes, all its dependent computed properties or render functions update.

Vue 2.x initializes the reactive properties by walking through each of them and creating custom getters and setters with Object.defineProperty(). Vue 3 uses Proxy objects to accomplish this.

Learn more about reactivity in Vue in this nicely illustrated article:

However, there are cases where we can’t initialize the data beforehand because we don’t know its structure (Some people might object that if we can’t predict our data structure then we’re doing something wrong, but let’s not dive into that discussion now). Imagine a scenario where we need to fetch the data of our users which comes as an array of objects.

"id": "p18Af0",
"name": "Chris"
"id": "lqR55z",
"name": "Sarah"

But right after we fetch them, we want to store them as an object using ids as the keys and names as the values. Why store them in this way? Maybe we’re trying to be efficient and have a map of users instead of an array. Therefore we don’t need to loop through it every time we search for a user by id.

"p18Af0": "Chris",
"lqR55z": "Sarah"

Our code might look like this.

const users = await api.getUsers();
users.forEach(user => {
this.users[] =;

Except that it wouldn’t work. Since the new properties of the this.users don’t have defined getters and setters they wouldn’t be reactive, thus Vue wouldn’t know when to update.

An easy solution to this would be to use this.$set() function

const users = await api.getUsers();
users.forEach(user => {

However, the preferred solution would be to completely replace the this.users object with a new one rather than calling the this.$set() function for each item.

const users = await api.getUsers();
const tempUsers = {};
users.forEach(user => {
tempUsers[] =;
this.users = tempUsers;


Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store