So, what happens with the data once passed to the Vue
instance? What are these transformations that Vue
applies to it so that it becomes so automatically bound to the View layer?
Let's analyze what would we do if we had, let's say, a string, and every time it changes we would like to apply some transformations to some DOM element. How would we apply the string-changing listener function? To what would we attach it? There is no such thing as var stringVar='hello';stringVar.onChange(doSomething)
.
So we would probably wrap the string's value setting and getting in some sort of function that would do something, for example, updating the DOM each time the string was updated. How would you implement it? While you're thinking about it, I'll prepare a quick demo of something interesting.
Open the developer tools on your shopping list application. Let's code a little bit. Create an obj
variable and another text
variable:
var obj = {}; var text = '';
Let's store the DOM element h2
in a variable:
var h2 = document.getElementsByTagName('h2')[0];
If we assign text
to the obj.text
property, how can we achieve that in every change of this property the innerHTML
of h2
would change as well?
Let's use the Object.defineProperty
method (
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
).
This method allows the creation of getter and setter functions, thus specifying what must happen when the property is accessed or changed:
Object.defineProperty(obj, 'text', {
get: function () {
return text;
},
set: function (newVal) {
text = newVal;
h2.innerHTML = text;
}
});
Now try to change the obj.text
property from the console. Look at the title:
The set method of object.defineProperty is called every time the property changes
This exact mechanism was used by Vue.js. Once the data are passed to the Vue
instance, all its properties go through the Object.defineProperty
method, which assigns reactive getters and setters to them. For each directive existing on a page, a watcher is added, which is being notified within the set
method. Open the vue.js
code in the console and search for the line that says set: function reactiveSetter(newVal)
. Add a breakpoint and try to change the title of the shopping list in the input. Now step over until you reach the last call in this function that says dep.notify()
:
Breakpoint inside the setter function that calls the watchers notify method
Step into the function. You will see that this function is iterating through the watchers of the property and updates them. If you step over this call, you will see that the DOM is not being updated. This is because the updates performed on the same event loop are being put into the queue that is being flushed periodically.
Find the runBatcherQueue
function and put a breakpoint inside it. Try to change the title again. As you can see, this function iterates through all the watchers that are waiting inside the queue and calls the run
method on each of them. If you step into this method, you will see that it compares the new value with the previous one:
if (value !== this.value ||...
It then it calls a callback's execution:
this.cb.call(this.vm, value, oldValue);
If you step into this callback function, you will see that in the end, it will finally update the DOM value:
update: function update(value) {
this.el[this.attr] = _toString(value);
}
Isn't it simple?
So the mechanism behind the Vue.js reactive data binding is very simple. Watchers are being assigned to all the directives and data properties. Then, during the set
method of Object.defineProperty
, the Watchers are notified and, in turn, they update the corresponding DOM or data:
The data flow from the data object to the DOM
DOM elements that have directives have attached listeners that listen to their updates and call the corresponding data property setter that, in turn, wakes up its Watchers.
18.117.192.177