How Vue Knows What Code Is Running
To be able to perform our sum anytime the numbers vary, our sum statement needs to be wrapped in a function:
const updateSum = () => {
sum = num1+ num2
}

You can also try this code with Online Javascript Compiler
Run Code
Vue keeps track of which function is presently running by using an effect. An effect is a wrapper around the function that commences tracking right before the function is called. Vue knows which effect is executing at any given instant and can re-run it when appropriate.
Let's try to create something like the effect wrapper but without Vue.
For this, we’ll need something to wrap around our summation:
createEffect(() => {
sum = val1 + val2
})

You can also try this code with Online Javascript Compiler
Run Code
We may implement the above effect something like this:
// Maintain a stack of running effects
const runningEffects = []
const createEffect = fn => {
// Wrap the passed fn in an effect function
const effect = () => {
runningEffects.push(effect)
fn()
runningEffects.pop()
}
// Automatically run the effect immediately
effect()
}

You can also try this code with Online Javascript Compiler
Run Code
When our effect is called, it puts itself onto the runningEffects array before invoking fn. Anything that needs to know which effect is currently running can check that array.
Effects act as the starting point for many crucial aspects. For example, both component rendering and calculated properties employ effects internally. Any time something magically responds to data changes, you can be quite sure it has been wrapped in an effect.
While Vue's public API doesn't contain any means to create an effect directly, it does expose a function called watchEffect that performs a lot like the createEffect function from our example.
How Vue Tracks These Changes
We can not track reassignments of local variables like those in our earlier instances, because there's just no method for accomplishing that with JavaScript. But we can track changes to object properties.
When we return a raw JavaScript object from a component's data function, Vue will encapsulate that object in a Proxy with handlers for get and set.
A proxy is an object that encases another object and allows you to intercept any interactions with that item.
We use it like this:
new Proxy (target, handler)

You can also try this code with Online Javascript Compiler
Run Code
const dinner = {
meal: 'tacos'
}
const handler = {
get(target, property) {
console.log('intercepted!')
return target[property]
}
}
const proxy = new Proxy(dinner, handler)
console.log(proxy.meal)
// intercepted!
// tacos

You can also try this code with Online Javascript Compiler
Run Code
Here we've intercepted attempts to read the properties of the target object. A handler function like this is sometimes known as a trap. There are numerous various types of traps available, each managing another kind of interaction.
One problem with using a Proxy is this binding. We want any methods to be tied to the Proxy rather than the target object so that we may intercept them also. Thankfully, ES6 brings another new feature, called Reflect, that allows us to make this problem disappear with no effort:
const dinner = {
meal: 'tacos'
}
const handler = {
get(target, property, receiver) {
return Reflect.get(...arguments)
}
}
const proxy = new Proxy(dinner, handler)
console.log(proxy.meal)
// tacos

You can also try this code with Online Javascript Compiler
Run Code
The first step towards developing Reactivity with a Proxy is to track when a property/variable is read. We do this in a function called track where we pass in the target and property, in handler:
const dinner = {
meal: 'tacos'
}
const handler = {
get(target, property, receiver) {
track(target, property)
return Reflect.get(...arguments)
}
}
const proxy = new Proxy(dinner, handler)
console.log(proxy.meal)
// tacos

You can also try this code with Online Javascript Compiler
Run Code
The implementation of the track isn't displayed here. It will check which effect is presently executing and store that alongside the target and property. This way Vue knows that the property depends on the impact.
Lastly, we need to re-run the effect when the property value changes. For this, we're going to require a set handler on our Proxy:
const dinner = {
meal: 'tacos'
}
const handler = {
get(target, property, receiver) {
track(target, property)
return Reflect.get(...arguments)
},
set(target, property, value, receiver) {
trigger(target, property)
return Reflect.set(...arguments)
}
}
const proxy = new Proxy(dinner, handler)
console.log(proxy.meal)
// tacos

You can also try this code with Online Javascript Compiler
Run Code
The proxied object is not visible to the user, but under the hood, it enables Vue to execute tracking dependencies and changes-notification when properties are accessed or modified.
If we want to rewrite our original example using a component we may do it as follows:
const vm = createApp({
data() {
return {
num1: 2,
num2: 3
}
},
computed: {
sum() {
return this.num1+ this.num2
}
}
}).mount('#app')
console.log(vm.sum) // 5
vm.num1= 3
console.log(vm.sum) // 6

You can also try this code with Online Javascript Compiler
Run Code
The object that data returns will be wrapped in a reactive proxy and stored as this.$data. The properties this.num1 and this.num2 are aliases for this.$data.num1 and this.$data.num2 respectively, so they go through the same Proxy.
Vue will wrap the function for the sum in an effect. When we try to access this.sum, the efect will be executed to calculate the value. The reactive Proxy around $data will track that the properties num1 and num2 were read while that effect runs.
Proxied Objects
Vue keeps track of all reactive objects internally, so it always returns the same proxy for the same object.
When a reactive proxy accesses a nested object, it converts the object to a proxy before returning it:
const handler = {
get(target, property, receiver) {
track(target, property)
const value = Reflect.get(...arguments)
if (isObject(value)) {
// Wrap the nested object in its own reactive proxy
return reactive(value)
} else {
return value
}
}
// ...
}

You can also try this code with Online Javascript Compiler
Run Code
How Rendering Reacts to Changes
A render function is created by compiling a component's template. The render function creates the VNodes that describe how the component should be drawn. It's wrapped in an effect, which allows Vue to keep track of which properties are 'touched' while it's running.
A calculated property is essentially comparable to a render function. Vue doesn't keep track of how dependencies are utilized; all it knows is that they were used at some time during the function's execution. If any of those properties change in the future, the effect will re-run, triggering the render function to build new VNodes. These are then used to make the required DOM changes.
FAQs
-
What is Reactivity in Vue?
The Vue JavaScript framework is "reactive," which means it can automatically refresh your data where changes are made. Data must be rendered dynamically in various HTML elements in modern online applications.
-
How does Vue reactivity work?
The reactive method in Vue allows you to construct a reactive state in JavaScript or Vue. The reactive method is essentially just a function that constructs a proxy and wraps it over specified data objects, resulting in a proxied object.
-
Are Vue methods reactive?
No, methods are not reactive. Only data can be reactive in Vue. It doesn't matter if you reference the data member directly, use it in computation or in a method.
Key takeaways
Reactivity is a model which helps in updating values of properties when the assigned values are altered. Vue uses Proxies to track the functions and achieve reactivity.
Check out this problem - Subarray Sum Divisible By K
Coding Ninjas brings to you a wide range of interesting blogs. To know more about web technologies please visit, Coding Ninjas Web Blogs.
Happy learning!!