Vue.js Asynchronous Update Queue
We just saw how Vue.js reacts to any changes that we make to our data properties and updates the DOM accordingly. This is great, but there’s something I didn’t tell you. It actually does this asynchronously. So even though it looks instant whenever we change a data property, this is actually not the case.
What happens under the hood, is that Vue uses a queue which acts as a buffer to all of the data changes that have been applied within the same event loop. So what is this so-called event loop? Well, you can think of it as a for loop that sometimes checks for changes that haven’t been applied to the DOM yet and applies them. So every now and then, the event loop “ticks,” and the queue of changes is flushed. Obviously this is a simplification, but hopefully that makes it easier to understand. The important thing to know is that there is a queue of changes that have not yet been applied to the DOM, meaning that these changes are not yet visible to the end user.
What’s cool, is that Vue actually de-dupes this queue, so if we change the same value twice within the same event loop (i.e. rapidly), then only the latest change is added to the queue. The point of this is to avoid manipulating the DOM unnecessarily, as well as redundant computations or calculations.
So why does this matter to us? Why should we even know this? Well, first of all it’s always good to have an idea what happens under the hood, but there may also be scenarios where knowing this is useful. Because the DOM is updated asynchronously, there is a small delay before the changes are applied. Usually this is not a problem and we won’t even notice it. Sometimes we may want to update the DOM directly, though, even though this is not recommended when working with a framework such as Vue. Sometimes, however, it may be necessary.
Suppose that we have the following code.
<div id="app">
{{ message }}
</div>
var vm = new Vue({
el: '#app',
data: {
message: 'Hello!'
}
});
So suppose we update a data property on a Vue instance, in this case the message property.
vm.message = ‘Hello World!’;
How do we know when the DOM has been updated? Well, let’s first verify that the DOM is not updated immediately, just to prove that I am telling you the truth in the first place. Perhaps you noticed that Vue instances contain a special property named $el. This property simply contains the root DOM element that the Vue instance manages and is of the type HTMLElement. In this example, this gives us access to the native DOM element that contains the app ID. Let’s just grab the text content of this element and output it in an alert dialog.
alert(vm.$el.textContent);
What do you think the alert is going to display?
It displays “Hello,” even though we clearly changed the value of the message data property on the line just above it. This is because the DOM is updated asynchronously as I mentioned before, and the event loop has not ticked yet and therefore the queue of changes has not been flushed. I hope that makes sense.
Okay, so now that we can clearly see that the DOM is not updated immediately after we make a change to a data property, when is it updated? There is a handy method available on the global Vue object named nextTick. This method takes a callback as its argument, which is invoked the next time Vue has updated the DOM.
Vue.nextTick(function() {
alert(vm.$el.textContent);
});
Let’s see which difference it makes.
So the first alert displays the same as we would expect, but the second one displays the updated message. This is because this alert is displayed at a point in time when the DOM has just been updated, i.e. when the nextTick method invokes its callback argument. Note that the call to the nextTick method should be placed immediately after changing data to make sure that the event loop does not “tick” before.
So if you for whatever reason need to manipulate the DOM right after having changed some data, then be careful that you don’t run into a race condition where the DOM does not look as you would expect. Hopefully you won’t need to do this very often, but it may be possible if integrating with a jQuery plugin or something like that. Either way, it’s good to know that the DOM is updated asynchronously even if you won’t need to actively deal with it.
Now that we know how Vue proxies data, how it reacts to data and when it updates the DOM, it’s time to talk about how Vue updates the DOM.
Here is what you will learn:
- How to build advanced Vue.js applications (including SPA)
- How Vue.js works under the hood
- Communicating with services through HTTP
- Managing state of large applications with Vuex
- ... and much more!