In order to reduce the mental burden, this paper only does the analysis of the principle and process, as far as possible does not involve vue.js source code. If you want to see a combination of source code analysis, I suggest a poke here: “Vue computing properties really cache? This article is the best Vue. Js principle analysis article I have ever seen, without one. The author wrote all vue.js principle analysis article is very good, I suggest that everyone can read and pay attention to the author (with my interests, and everyone’s interests related ah)

This is the second article in watcher’s series

  • Vue: Render Watcher
  • Name a few Watchers in Vue (2), computed Watcher
  • Vue watcher (2) — Regular Watcher (to be continued)

Usage scenarios

Where can computed attribute values be used in general? Let’s talk about two common simple examples

  • Example 1: in the template
    export default {
      template: '<div>My name is {{ fullname }}</div>',
      data () {
        return {
          firstName: 'Steve'.lastName: 'Jobs'}},computed: {
        fullName: ({ firstName, lastName }) = > `${firstName},${lastName}`}}Copy the code
  • Example 2: templates, and other computed properties
    export default {
      template: '<div>{{ selfIntroduction }}</div>',
      data () {
        return {
          firstName: 'Steve'.lastName: 'Jobs'}},computed: {
        fullName: ({ firstName, lastName }) = > `${firstName},${lastName}`.selfIntroduction: ({ fullName }) = > `My name is ${fullName}`}}Copy the code

Establish contact

Having looked at the above usage scenarios, the question we should ask is:

  • The value of the data property has changed. How do I know about computed property?
  • How does the template rendering function know if computed property values change?

After the introduction of render- Watcher in the last section, we should have a general idea:

  • You have to create a Watcher for a computed property (exactly computed- Watcher) and add it to the subscriber queue for the value of the associated data property. Watcher’s callback is exactly computed property values
  • Changes in computed attribute values are caused by changes in the data attribute. So if you want the template to change, render- Watcher has to be added to the subscriber queue for the data associated with computed attributes.

    A bit around? In contrast to code example 1 above, it is render-watcher that has to be added tofirstNameandlastNameIn the subscriber queue

So let’s see how do we make this connection

Depend on the collection

Initialization of a computed attribute

Start by initializing the computed property.

After access hijacking of all data attribute values is complete, we enter the initialization process for computed attributes:

  • Iterate over computed properties, creating a Watcher for each computed property;
  • Iterate over computed properties, and get hijack each computed property

Among them, get hijacking is the most critical step. In this section, the solution we proposed above is implemented:

  • Add computed- Watcher to the subscriber queue for the data attribute value.
  • Adds render- Watcher to the subscriber queue for the value of the data property.

When the value of the data attribute changes:

  • Render function execution
  • Computed property function executes and returns the result of the new execution

Let’s see how this works:

Get hijacking of computed attributes

The gears turn when the render function is executed.

When the Render function executes, it triggers a GET for computed property values.

Then, in get, several things happen in order:

  • Perform a computed property function to save the return value of the function

    Notice that during a computed function, the value of the data property gets.

  • The data attribute value adds the current watcher for the computed attribute to the subscription queue

  • The data attribute value adds render-watcher to the subscription queue

  • Returns the result of a saved computed function execution

Note the order in the subscription queue, computed-watcher first, render-watcher after.

All right, the first run of the gears is over.

Even with the reaction

The template directly references computed properties

The value of the data property has been changed. For example, let’s modify the lastName attribute in Example 1: this.lastName = ‘Nash’

Okay, so what happens at this point?

Yes, the gears are turning once again.

  • The value of the data property is set
  • The data property value notifies all subscribers that you are about to update
  • Computed – Watcher executes the computed property function and returns the new value
  • Render – Watcher executes the render callback to render the new view

Logical readers may already be wondering:

The compute-Watcher callback executes computed once, and the render- Watcher callback triggers a get for computed property that executes computed again. Isn’t this twice executed?

Right! That’s no good! We can only pick a Watcher and trigger the execution of the computed function in its callback. Do it:

  • In the compute-Watcher callback, we mark the computed property as “to be updated”
  • When render-watcher→render function →computed property values get, see if there is a “to update” flag, perform computed function if there is, and cancel the “to update” flag when it is done. Does not directly return the result saved from the last execution

Extract the core logic above and use pseudocode to express it:

If (dirty) {setComputedValueCache(update()) dirty = false} return getComputedValueCache()Copy the code

In short, the cached value is returned each time. The cache value is not updated until it returns.

So far, we’ve figured out how to be responsive when using computed property values in templates; We also know what, what and how computed-watcher is used.

With that in mind, let’s take a look at example 2 above, which is: What happens when a computed property references a computed property?

The template indirectly references computed properties

What is an indirect reference to computed attributes? As you can see from example 2 above, the chain of references is as follows:

Template → Computed attribute 1 → computed attribute 2 → Data attribute value

Computed attribute 2 is an indirect reference to a template.

After the above, presumably we do not need to start the analysis from scratch (liver immobility 😂😂😂). Look directly at the subscription queue at the end of the data attribute:

Data attribute value → [computed-watcher1, computed-watcher2, render-watcher].

When the data attribute value is set, computed-watcher1 and computed-watcher2 are marked “to be updated” successively. When render- Watcher is updated, it will execute in order:

  • Render function
  • Computed1 Attribute is get
  • Computed1 Attribute function execution
  • Computed2 attribute is get
  • Computed2 Attribute function execution
  • Caches and returns computed2 results to Computed1
  • Caches and returns computed1 results to the render function
  • The render function renders the computed1 new value into the view

So now we have a basic, simple idea of computed watcher.