SoFunction
Updated on 2025-03-10

Compute properties and listener details

1. Calculate properties

Expressions within templates are very convenient, but they were designed for simple operations. Putting too much logic into a template can make the template too heavy and difficult to maintain.

For example:

<div >
  {{ ('').reverse().join('') }}
</div>


In this place, templates are no longer simple declarative logic. You have to look at it for a while to realize that here is the one that wants to display the variablemessage flip string. It's even harder to handle when you want to include this flipped string in multiple places in the template.

So, for any complex logic, you should use computed properties.

1.1 Basic examples

&lt;div &gt;
  &lt;p&gt;Original message: "{{ message }}"&lt;/p&gt;
  &lt;p&gt;Computed reversed message: "{{ reversedMessage }}"&lt;/p&gt;
&lt;/div&gt;
var vm = new Vue({
  el: '#example',
  data: {
    message: 'Hello'
  },
  computed: {
    // Getter for calculating properties    reversedMessage: function () {
      // `this` points to vm instance      return ('').reverse().join('')
    }
  }
})


result:

Original message: "Hello"

Computed reversed message: "olleH"

Here we declare a computed propertyreversedMessage. The functions we provide will be used as property ofgetter function:

() // => 'olleH'
 = 'Goodbye'
() // => 'eybdooG'


You can open the browser console and modify the examplevm The value of value.

You can be like bindingproperty Also bind computed properties in the template. Vue knows Depend on, therefore when When changes occur, all dependencies The bindings will also be updated. And the best thing is that we have created this dependency in a declarative way: computed attributesgetter Functions have no side effects, which makes them easier to test and understand.

1.2 Computing attribute cache vs method

You may have noticed that we can achieve the same effect by calling methods in expressions:

&lt;p&gt;Reversed message: "{{ reversedMessage() }}"&lt;/p&gt;
// In the componentmethods: {
  reversedMessage: function () {
    return ('').reverse().join('')
  }
}


We can define the same function as a method instead of a computed property. The end result of both methods is indeed exactly the same. However, the difference is that computed properties are cached based on their responsive dependencies. They are re-evaluated only when relevant responsive dependencies change. This means thatmessage Haven't changed yet, many visitsreversedMessage The computed property will immediately return the previous computed result without having to execute the function again.

This also means that the following computed properties will no longer be updated because () is not a responsive dependency:

computed: {
  now: function () {
    return ()
  }
}


By contrast, whenever re-render is triggered, the calling method will always execute the function again.

Why do we need cache? Suppose we have a computational attribute with relatively high performance overheadA, it needs to iterate through a huge array and do a lot of calculations. Then we may have other computed properties that depend onA. Without cache, we will inevitably execute multiple timesA ofgetter! If you don't want a cache, please use a method instead.

1.3 Computing properties vs listening properties

Vue Provides a more general way to observe and respondVue Data changes on instances: Listening properties. When you have some data that needs to change with other data, it is easy for you to abuse itwatch——Especially if you have used it beforeAngularJS. However, it is usually better to use computed properties instead of imperative oneswatch Callback.

Think about this example:

<div >{{ fullName }}</div>
var vm = new Vue({
  el: '#demo',
  data: {
    firstName: 'Foo',
    lastName: 'Bar',
    fullName: 'Foo Bar'
  },
  watch: {
    firstName: function (val) {
       = val + ' ' + 
    },
    lastName: function (val) {
       =  + ' ' + val
    }
  }
})


The above code is imperative and repeated. Compare it to the version of the computed attribute:

var vm = new Vue({
  el: '#demo',
  data: {
    firstName: 'Foo',
    lastName: 'Bar'
  },
  computed: {
    fullName: function () {
      return  + ' ' + 
    }
  }
})

Much better, isn't it?

1.4 Computing the setter of properties

The computed attribute has only getter by default, but you can also provide a setter when needed:

// ...
computed: {
  fullName: {
    // getter
    get: function () {
      return  + ' ' + 
    },
    // setter
    set: function (newValue) {
      var names = (' ')
       = names[0]
       = names[ - 1]
    }
  }
}
// ...

Run again now = 'John Doe' hour,setter Will be called, and It will also be updated accordingly.

2. Listener

While computed properties are more appropriate in most cases, sometimes a custom listener is required. that's whyVue passwatch Options provide a more general way to respond to changes in data. This method is most useful when it is necessary to perform asynchronous or overhead operations when data changes.

For example:

&lt;div &gt;
  &lt;p&gt;
    Ask a yes/no question:
    &lt;input v-model="question"&gt;
  &lt;/p&gt;
  &lt;p&gt;{{ answer }}&lt;/p&gt;
&lt;/div&gt;
&lt;!-- because AJAX The ecosystem of libraries and general tools is already quite rich,Vue The core code is not duplicated --&gt;
&lt;!-- Provide these features to keep them streamlined。This also gives you the freedom to choose tools that you are more familiar with.。 --&gt;
&lt;script src="/npm/[email protected]/dist/"&gt;&lt;/script&gt;
&lt;script src="/npm/[email protected]/"&gt;&lt;/script&gt;
&lt;script&gt;
var watchExampleVM = new Vue({
  el: '#watch-example',
  data: {
    question: '',
    answer: 'I cannot give you an answer until you ask a question!'
  },
  watch: {
    // If `question` changes, this function will run    question: function (newQuestion, oldQuestion) {
       = 'Waiting for you to stop typing...'
      ()
    }
  },
  created: function () {
    // `_.debounce` is a function that limits the frequency of operations through Lodash.    // In this example, we want to limit the frequency of access to /api    // AJAX request will not be issued until the user enters it.  Want to learn more about    // Knowledge of the `_.debounce` function (and its close relatives `_.throttle`),    // Please refer to: /docs#debounce     = _.debounce(, 500)
  },
  methods: {
    getAnswer: function () {
      if (('?') === -1) {
         = 'Questions usually contain a question mark. ;-)'
        return
      }
       = 'Thinking...'
      var vm = this
      ('/api')
        .then(function (response) {
           = _.capitalize()
        })
        .catch(function (error) {
           = 'Error! Could not reach the API. ' + error
        })
    }
  }
})
&lt;/script&gt;

result:

Ask a yes/no question:

I cannot give you an answer until you ask a question!

In this example, usewatch The option allows us to perform asynchronous operations (access an API), limits how often we perform the operation, and sets an intermediate state before we get the final result. These are all things that computed properties cannot do.

This is the end of this article about the details of computing properties and listeners. For more related computing properties and listeners, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!