Skip to content

Understanding vue3 reactivity fundamentals with examples.

Posted on:January 25, 2023

Vue3 is a popular JavaScript framework for building user interfaces. One of the key features of Vue3 is its reactivity system, which allows the framework to automatically update the view when the data changes. In this article, we’ll take a closer look at the fundamentals of Vue3’s reactivity system and how it works.

First, it’s important to understand that Vue3 uses a reactive data model. This means that when a piece of data is changed, the view that is connected to that data will automatically update. This is in contrast to a non-reactive data model, where the developer would need to manually update the view when the data changes.

The reactivity system in Vue3 is built on top of JavaScript’s Object.defineProperty() method, which allows the framework to intercept when a property on an object is accessed or modified. When a property is accessed or modified, Vue3 can then update the view accordingly.

One of the key concepts in Vue3’s reactivity system is the “reactivity dependency”. A reactivity dependency is created whenever a piece of data is accessed or modified. For example, when a component’s template references a piece of data, Vue3 creates a reactivity dependency between the component and the data.

When the data is changed, Vue3 will then update the component’s view to reflect the change. This process is known as “reactivity tracking”.

Vue3 also provides a way for developers to create their own reactivity dependencies using the $watch() method. This method allows developers to track changes to a specific piece of data and execute a callback function when the data changes.

One of the advantages of Vue3’s reactivity system is that it is efficient. Since Vue3 only updates the view when the data changes, it avoids unnecessary updates and improves the performance of the application.

Another advantage of Vue3’s reactivity system is that it makes it easy for developers to create dynamic, responsive user interfaces. By connecting the view to the data, Vue3 allows developers to create interfaces that automatically update when the data changes, without the need for manual updates.

It’s worth noting that Vue3’s reactivity system is not limited to the view layer. Developers can also use the reactivity system in other parts of the application, such as in computed properties, watchers, and lifecycle hooks.

If you’re interested in learning more about Vue3’s reactivity system, here are some external resources that you might find helpful:

Using Vue3’s reactivity system

  1. Using the v-model directive to bind data to a input element:
<template>
  <div>
    <input v-model="message" placeholder="Enter a message">
    <p>{{ message }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      message: ''
    }
  }
}
</script>

In this example, we’re using the v-model directive to bind the value of an input element to a data property named “message”. Whenever the user types something in the input field, the “message” property is updated, and the view updates to reflect the change. This creates a reactivity dependency between the input element and the “message” property.

  1. Using the $watch() method to track changes to a data property:
<template>
  <div>
    <button @click="incrementCounter">Increment</button>
    <p>{{ counter }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      counter: 0
    }
  },
  created() {
    this.$watch('counter', (newValue, oldValue) => {
      console.log(`Counter changed from ${oldValue} to ${newValue}`);
    })
  },
  methods: {
    incrementCounter() {
      this.counter++;
    }
  }
}
</script>

In this example, we’re using the $watch() method to track changes to the “counter” property. Whenever the “counter” property is updated, the callback function passed to $watch() is executed, and a message is logged to the console. This creates a reactivity dependency between the “counter” property and the $watch() method.

  1. Using computed properties to create a reactive property:
<template>
  <div>
    <p>{{ message }}</p>
    <p>{{ reversedMessage }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      message: 'Hello, Vue3!'
    }
  },
  computed: {
    reversedMessage() {
      return this.message.split('').reverse().join('');
    }
  }
}
</script>

In this example, we have a computed property named “reversedMessage” that returns the reverse of the “message” property. The computed property creates a reactivity dependency between the “message” property and the “reversedMessage” property so that when message change the computed property will recalculate the value and update the view.

In all these examples the reactivity system of Vue3 is working in the background, allowing the view to update automatically when the data changes.

Bonus: Creating a two way binding like v-model with vanilla Javascript.

Here’s an example of how you can recreate the functionality of the v-model directive using vanilla JavaScript:

<template>
  <div>
    <input id="message-input" placeholder="Enter a message">
    <p id="message-output"></p>
  </div>
</template>

<script>
export default {
  created() {
    // Get the input and output elements
    const input = document.getElementById('message-input');
    const output = document.getElementById('message-output');

    // Create a data property to store the message
    this.message = '';

    // Listen for changes to the input element
    input.addEventListener('input', (event) => {
      // Update the data property with the new value
      this.message = event.target.value;

      // Update the output element with the new value
      output.innerHTML = this.message;
    });
  }
}
</script>

In this example, we’re using the addEventListener method to listen for changes to the input element. When the input event is fired, we update a data property named “message” with the new value of the input element, and we update the output element with the new value of the message property.

This is a simple example of how you can use vanilla JavaScript to create a two-way binding between a form element and a data property, similar to the functionality provided by the v-model directive in Vue3.

It’s worth noting that this example is very basic and does not cover all of the functionality provided by the v-model directive. The v-model directive provides several features such as lazy, number, trim, and more.

Additionally, the v-model directive also provide some other features like cross-browser compatibility, event handling, and is more optimized for performance. It is always recommended to use the Vue’s provided directives and features as it is built and optimized for the framework.