From Vue.js in Action by Erik Hanchett

Because computed properties are typically calculated using instance data, their return value is updated automatically when the underlying data changes. Any view markup bound to the computed property is updated to reflect the new value as well.

This behavior is at the heart of the update cycle within the greater Vue instance lifecycle—let’s have a look…


Save 37% on Vue.js in Action. Just enter code fcchanchett into the discount code box at checkout at manning.com.


To get a feel for how the Vue update cycle behaves, let’s work through another example of when a computed property is a perfect fit for the job. Consider the task of computing the area of a rectangle, based on its length and width.

Listing 1. Computing the area of a rectangle — chapter-03/computed-rect.js

 
 new Vue({
   data: {
     length: 5,                             ❶ 
     width: 3                               ❶ 
   },
   computed: {
     area: function() {                     ❷ 
       return this.length * this.width;     ❷ 
     }                                      ❷ 
   }
 });
 

❶   A data object containing length and width properties

❷   A computed property exposes area the same as a data property

The computed property area has an initial value of 15. Any subsequent change to length or width triggers a series of updates to the application.

  1. When the value of length or width is changed …
  2. The computed property area is recalculated, then …
  3. Any markup bound to these properties is updated.

Figure 1. Changes in an instance’s data trigger a cascade of activity within the update cycle of an application.


We can see the lifecycle in action by using watch functions to observe when the data in an instance changes, and the beforeUpdate lifecycle hook, which should be executed only after the data has changed.

INFO A watch function works like a lifecycle hook, but it’s triggered when the data it’s “watching” is updated. We can even create a watch function to observe a computed property.

Listing 2 puts our area calculation in the context of a complete application. The application also contains three watch functions that log messages to the console whenever length, width, or area change, and one function to log when the update cycle begins. These functions must be specified in the watch option of the Vue instance for them to work.

TIP You can find the code for this listing in the samples that accompany this article in the file chapter-03/area.html. It’s entirely self-contained, and you can open it directly in Chrome.

Listing 2 Computed properties and update event logging – chapter-03/area.html

 
 <html>
 <head>
   <title>Calculating Area - Vue.js in Action</title>
   <script src="https://unpkg.com/vue/dist/vue.js"
     type="text/javascript"></script>
 </head>
 <body>
   <div id="app">
     <p>
       Area is equal to: {{ area }}                             ❶ 
     </p>
     <p>
       <button v-on:click="length += 1">Add length</button>     ❷ 
       <button v-on:click="width += 1">Add width</button>       ❷ 
     </p>
   </div>
   <script type="text/javascript">
     var app = new Vue({
       el: '#app',
       data: {
         length: 5,                                             ❸ 
         width: 3                                               ❸ 
       },
       computed: {
         area: function() {                                     ❹ 
           return this.width * this.length;                     ❹ 
         }                                                      ❹ 
       },
       watch: {
         length: function(newVal, oldVal) {                     ❺ 
           console.log('The old value of length was: '          ❺ 
                       + oldVal +                               ❺ 
                       '\nThe new value of length is: '         ❺ 
                       + newVal);                               ❺ 
         },
         width: function(newVal, oldVal) {                      ❻ 
           console.log('The old value of width was: '           ❻ 
                       + oldVal +                               ❻ 
                       '\nThe new value of width is: '          ❻ 
                       + newVal);                               ❻ 
         },
         area: function(newVal, oldVal) {                       ❼ 
           console.log('The old value of area was: '            ❼ 
                       + oldVal +                               ❼ 
                       '\nThe new value of area is: '           ❼ 
                       + newVal);                               ❼ 
         }
       },
       beforeUpdate: function() {                               ❽ 
         console.log('All those data changes happened '         ❽ 
                     + 'before the output gets updated.');      ❽ 
       }
     });
   </script>
 </body>
 </html>
 

❶   Data binding that displays the value of area

❷   Buttons that increase the value of length or width by 1, respectively

❸   Original values for length and width

❹   The area computed property

❺   Function that logs when length changes

❻   Function that logs when width changes

❼   Function that logs when area changes

❽   beforeUpdate lifecycle hook function

When you load this file in Chrome, you’ll see an initial value for area of 15.


Figure 2. The initial state of our area calculating application.


Be sure the JavaScript console is open, then try clicking the buttons to trigger the update cycle. The console should log messages about the application’s data when the “Add length” button and “Add width” button are clicked.


Figure 3. Observing our properties changing in response to clicking buttons.


Now that we’ve seen how the application behaves, we can map the data and functions from listing 2 onto our diagram of the update cycle.


Figure 4. Changes in an instance’s data trigger a cascade of activity within the update cycle of an application.


One last thing to note, if you remove the {{ area }} binding from the sample code, and reload the page in your browser, you’ll see a difference in the console output when you click on either button.


Figure 5. No update message displays if nothing gets updated.


With no outlet for the computed property, there’s nothing to update, and therefore no reason to enter the update cycle. This means the beforeUpdate function won’t get executed and the corresponding message won’t get logged to the console.

And that’s how the Vue update cycle works!


For more of Vue.js in Action, read the free first chapter here and see this slide deck.