Vue's Reactivity System, A Deep Dive

Vue's Reactivity System, A Deep Dive

Hello there, welcome to my blog. Vue is such an interesting tool to work with, for the past couple of weeks I have spent a lot of time learning it, and not just learning it, but learning the underlying concepts as this gives me an edge when using it. Understanding a framework behind the scenes is really interesting. Vue is fast and reacts to changes in data and updates the DOM with lightning speed, have you ever asked yourself why? Like yeah, why. Coming from JavaScript I have never seen anything like that. Well, Vue uses a programming concept called Reactive programming, which is what enables Vue reactivity system.

Sounds strange? Relax, the aim of this article is the demystify the Vue reactivity system and makes you understand what Vue does under the hood. Grab some popcorn, this would be fun trust me.

Prerequisite

  • Basic understanding of Vue.
  • Basic knowledge of JavaScript.

What is Reactive Programming?

Reactive programming is programming with asynchronous data streams.

Yeah, that just it. Sounds funny? Typical click event, user inputs e.t.c are data streams, it can be anything from hover, variables, data structures, arrays, e.t.c. Now programming with these data streams is what is called Reactive programming. You can hook into any stage of the data streams.

A stream is a sequence of ongoing events ordered in time. For example, let take a look at a hover effect, there are 3 data streams there; the time the mouse hovers over it, the actions that take place after the hovering of the mouse, and when the mouse leaves, with reactive programming we can listen to that data stream and react accordingly.

reactive.png

How does Vue use Reactive programming?

First off, frontend frameworks like React and Angular make use of reactive programming to react to data changes either from an API or from user activity, well that is what most of frontend development is focused on "reacting and interacting with the user".

Vue makes use of Reactive programming heavily when rendering data and attending to changes in data. When we write Vue code, we know the browser doesn't understand it, so what Vue does is to change that Vue code and style to native JavaScript and pass it for the browser to execute. Let look at how Vue converts a component to JavaScript.

In a Vue component, there is a data object that returns an object with properties that we can use in our templates.

// Vue 
<template>
   <h2> {{ name }} </h2>
</template>

<script>
export default {
data(){
return{
      name: "Mike Thompson",

}
},
method:{
sayHello(){
console.log("Good morning"+ this.name")
    }
}

}
</script>

The code above when executed by Vue is stored in a global object in the Virtual DOM, this will also include computed properties, life cycle hooks, watchers e.t.c and given to JavaScipt, now let see that.


// Vue converted to JavaScript
const global = {
    name: "Mike Thompson",
   sayHello(){
   console.log(" Good morning "+ this.name")
     }
}

From the code, above you can see Vue made the function in the Vue methods an object method in the global object, ever wondered why the functions in Vue are referred to as methods just like the one in the above Vue code snippet, well here is why, because after the conversion to JavaScript they indeed become a JavaScript object method. Is this making sense?. Finally, in the Vue code snippet above you can see how the use of the this keyword was used to get values of the object property, this is because under the hood the data and the methods object are part of a global object, and in JavaScript, we use the this keyword to get values of the object properties.

So that is a breakdown of how Vue converts the code written to JavaScript, this will help us understand better how Vue uses Reactive programming to work. Read on.

A change in any of those data properties would update in the DOM with lightning speed since that part of the DOM uses the data value. But how does Vue does this?

  • Detect if there is a change in any of the values.
  • Track the function to change it.
  • Trigger the function and update the value.

All those happen under a millisecond, now the big question is what function is Vue tracking? how is it triggering the function? The first time, this was not making sense to me, but I am here to explain all of that. So take a deep breath, take a handful of your popcorn and let continue.

JavaScript is not reactive.

Let take a look at the code below:

let message = "Hello"
let longMessage = message + ' World'
console.log( longMessage)

// 'Hello World'

message = "Hello!!!!"
console.log( longMessage)

// 'Hello World'

See what happened right there? JavaScript didn't update the message variable, even when we clearly reassigned it. This is the issue Vue came to solve, from the code above we can agree that JavaScript is not reactive by default.

How Vue reacts to changes

Beneath the hood, Vue uses a JavaScript ES6 feature call Proxy wrap our global object( I discussed that above) to track changes and update the data values based on the changes. Let see how the JavaScript Proxy works.

const global= {
  name: "Mike Thompson",
}

const handler={
set(target, key, value){
console.log(target)
console.log(key)
console.log(value)
  }
}

const proxy = new Proxy(global, handler)

proxy.name = "James Bond"

The Output:

// { message: "Mike Thompson" }
// message
// "James Bond"

Let me explain what is going on up there.

A JavaScript Proxy accepts two arguments; (the object to be tracked) and (the object to track it), the object used to track the change is called a handler. Now, in the handler object, we have 2 functions which are namely get() and set() which are called Traps. get() is used to get the data changed and what changes while set() just as the name implies is used to set the new value when the data is changed and it automatically provides 3 arguments we can use to set changes target, key and value. The target is the object where the change happened as we see above, the key is the object key where the change happened, while the value is what changed. From the output you can see that.

The Proxy wraps the "object to be tracked" and thereby gets access to the properties in that object, which means we can use the Proxy to change the value of properties as we want which I did above, and the handler on it part gets these changes and sets them. From the output of the code snippet above, you can see the value of the name property changed.

To make this more clear, let's have another code snippet.

const global= {
  message: " Hello ",
 longMessage: "Hello!! World"
}

const handler={
set(target, key, value){

  }
}

const proxy = new Proxy(global, handler)

From the above snippet, what I want to achieve is to make longMessage change when the message property changes. Let do that, oops take a handful of popcorn.

const global= {
  name: "Hello",
}

const handler={
set(target, key, value){
  if(key === ' message ' ){
     target.longMessage = value + ' World '
}
 target.message = value;
  }
}

const proxy = new Proxy(global, handler)

proxy.message= "Hy"

console.log ( proxy.longMessage)

Output :


// "Hy World"

I know that is a lot of code, but let me explain what is going on there, I asked the set function to watch if what I am changing has the property of message, if yes, I want the longMessage to take the new value and attach to " World ". Then I reassign the message property to take the new value.

So when we changed the value of the message property using the proxy the handler fired the set function and updated the necessary things, now this brings us back to the solution on how Vue tracks and updates data changes:

  • Detect if there is a change in any of the values.
  • Track the function to change it.
  • Trigger the function and update the value.

Vue wraps the global object with a Proxy and makes a handler that tracks those changes and updates them in accordinly.

You have seen how Vue uses the Proxy feature to track changes and updates the data based on the changes, now imagine writing all that code for your JavaScript application? That would be strenuous and give us a messy codebase and we will have to track different object properties and react to them. But here you go, Vue is doing that for us under the hood, using the Reactive programming concept as it enables us to program and run codes based on data streams and events.

The objective of this article is not for you to ram up those codes or start writing Proxy, nope but rather to make you understand how Vue uses the JavaScript proxy to achieve its Reactive nature and any day you may want to dabble into the Vue codebase to make open-source contributions, you can probably understand how the codes are written.

Resources

In conclusion

With this knowledge, you should have an understanding of Reactive programming and how the Vue reactivity system works. Hope you grabbed something? and did you finish your popcorn?

So we have come to the end of this amazing article. Hope you learned something useful. If you did, like, share, comment, just do anything to make it go viral.

I would be posting more articles, so be sure to follow me to get notified when I post them.

If you have any questions concerning Go, Javascript, TailwindCSS, Open-source, or this article? You can reach me on Twitter. Till next time, see ya. Thank you.