[go: up one dir, main page]

0% found this document useful (0 votes)
81 views7 pages

Computed Properties and Watchers

Computed properties allow you to calculate derived data based on reactive dependencies. They are cached based on dependencies so the function only re-runs when dependencies change. Watchers can be used for asynchronous operations or expensive computations instead of computed properties. Computed properties are generally preferred for simple synchronous derivations, while watchers are more appropriate when needing to react to asynchronous or expensive operations.

Uploaded by

Nelson
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
81 views7 pages

Computed Properties and Watchers

Computed properties allow you to calculate derived data based on reactive dependencies. They are cached based on dependencies so the function only re-runs when dependencies change. Watchers can be used for asynchronous operations or expensive computations instead of computed properties. Computed properties are generally preferred for simple synchronous derivations, while watchers are more appropriate when needing to react to asynchronous or expensive operations.

Uploaded by

Nelson
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 7

Computed Properties and Watchers

vuejs.org/v2/guide/computed.html

#BlackLivesMatter Support the Equal Justice Initiative.

Vue.js
Team

Computed Properties
Learn how computed properties work with a free lesson on Vue School
In-template expressions are very convenient, but they are meant for simple operations.
Putting too much logic in your templates can make them bloated and hard to maintain.
For example:

<div id="example">
{{ message.split('').reverse().join('') }}
</div>

At this point, the template is no longer simple and declarative. You have to look at it for
a second before realizing that it displays message in reverse. The problem is made
worse when you want to include the reversed message in your template more than once.

That’s why for any complex logic, you should use a computed property.

Basic Example
1/7
<div id="example">
<p>Original message: "{{ message }}"</p>
<p>Computed reversed message: "{{ reversedMessage }}"</p>
</div>

var vm = new Vue({


el: '#example',
data: {
message: 'Hello'
},
computed: {

reversedMessage: function () {

return this.message.split('').reverse().join('')
}
}
})

Result:

Original message: "{{ message }}"

Computed reversed message: "{{ reversedMessage }}"

Here we have declared a computed property reversedMessage . The function we


provided will be used as the getter function for the property vm.reversedMessage :

console.log(vm.reversedMessage)
vm.message = 'Goodbye'
console.log(vm.reversedMessage)

You can open the console and play with the example vm yourself. The value of
vm.reversedMessage is always dependent on the value of vm.message .

You can data-bind to computed properties in templates just like a normal property. Vue
is aware that vm.reversedMessage depends on vm.message , so it will update any
bindings that depend on vm.reversedMessage when vm.message changes. And the
best part is that we’ve created this dependency relationship declaratively: the computed
getter function has no side effects, which makes it easier to test and understand.

Computed Caching vs Methods


You may have noticed we can achieve the same result by invoking a method in the
expression:

<p>Reversed message: "{{ reverseMessage() }}"</p>

2/7
methods: {
reverseMessage: function () {
return this.message.split('').reverse().join('')
}
}

Instead of a computed property, we can define the same function as a method. For the
end result, the two approaches are indeed exactly the same. However, the difference is
that computed properties are cached based on their reactive dependencies.
A computed property will only re-evaluate when some of its reactive dependencies have
changed. This means as long as message has not changed, multiple access to the
reversedMessage computed property will immediately return the previously
computed result without having to run the function again.

This also means the following computed property will never update, because
Date.now() is not a reactive dependency:

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

In comparison, a method invocation will always run the function whenever a re-render
happens.

Why do we need caching? Imagine we have an expensive computed property A, which


requires looping through a huge Array and doing a lot of computations. Then we may
have other computed properties that in turn depend on A. Without caching, we would
be executing A’s getter many more times than necessary! In cases where you do not
want caching, use a method instead.

Computed vs Watched Property


Vue does provide a more generic way to observe and react to data changes on a Vue
instance: watch properties. When you have some data that needs to change based on
some other data, it is tempting to overuse watch - especially if you are coming from an
AngularJS background. However, it is often a better idea to use a computed property
rather than an imperative watch callback. Consider this example:

<div id="demo">{{ fullName }}</div>

3/7
var vm = new Vue({
el: '#demo',
data: {
firstName: 'Foo',
lastName: 'Bar',
fullName: 'Foo Bar'
},
watch: {
firstName: function (val) {
this.fullName = val + ' ' + this.lastName
},
lastName: function (val) {
this.fullName = this.firstName + ' ' + val
}
}
})

The above code is imperative and repetitive. Compare it with a computed property
version:

var vm = new Vue({


el: '#demo',
data: {
firstName: 'Foo',
lastName: 'Bar'
},
computed: {
fullName: function () {
return this.firstName + ' ' + this.lastName
}
}
})

Much better, isn’t it?

Computed Setter
Computed properties are by default getter-only, but you can also provide a setter when
you need it:

4/7
computed: {
fullName: {

get: function () {
return this.firstName + ' ' + this.lastName
},

set: function (newValue) {


var names = newValue.split(' ')
this.firstName = names[0]
this.lastName = names[names.length - 1]
}
}
}

Now when you run vm.fullName = 'John Doe' , the setter will be invoked and
vm.firstName and vm.lastName will be updated accordingly.

Watchers
While computed properties are more appropriate in most cases, there are times when a
custom watcher is necessary. That’s why Vue provides a more generic way to react to
data changes through the watch option. This is most useful when you want to perform
asynchronous or expensive operations in response to changing data.

For example:

<div id="watch-example">
<p>
Ask a yes/no question:
<input v-model="question">
</p>
<p>{{ answer }}</p>
</div>

5/7
<script src="https://cdn.jsdelivr.net/npm/axios@0.12.0/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/lodash@4.13.1/lodash.min.js"></script>
<script>
var watchExampleVM = new Vue({
el: '#watch-example',
data: {
question: '',
answer: 'I cannot give you an answer until you ask a question!'
},
watch: {

question: function (newQuestion, oldQuestion) {


this.answer = 'Waiting for you to stop typing...'
this.debouncedGetAnswer()
}
},
created: function () {

this.debouncedGetAnswer = _.debounce(this.getAnswer, 500)


},
methods: {
getAnswer: function () {
if (this.question.indexOf('?') === -1) {
this.answer = 'Questions usually contain a question mark. ;-)'
return
}
this.answer = 'Thinking...'
var vm = this
axios.get('https://yesno.wtf/api')
.then(function (response) {
vm.answer = _.capitalize(response.data.answer)
})
.catch(function (error) {
vm.answer = 'Error! Could not reach the API. ' + error
})
}
}
})
</script>

Result:

Ask a yes/no question:

6/7
{{ answer }}

In this case, using the watch option allows us to perform an asynchronous operation
(accessing an API), limit how often we perform that operation, and set intermediary
states until we get a final answer. None of that would be possible with a computed
property.

In addition to the watch option, you can also use the imperative vm.$watch API.

7/7

You might also like