Computed Properties
Remarks#
Data vs Computed Properties
The main use-case difference for the data
and computed
properties of a Vue
instance is dependent on the potential state or probability of changing of the data. When deciding what category a certain object should be, these questions might help:
- Is this a constant value? (data)
- Does this have the possibility to change? (computed or data)
- Is the value of it reliant on the value of other data? (computed)
- Does it need additional data or calculations to be complete before being used? (computed)
- Will the value only change under certain circumstances? (data)
Basic Example
Template
<div id="example">
a={{ a }}, b={{ b }}
</div>
JavaScript
var vm = new Vue({
el: '#example',
data: {
a: 1
},
computed: {
// a computed getter
b: function () {
// `this` points to the vm instance
return this.a + 1
}
}
})
Result
a=1, b=2
Here we have declared a computed property b
. The function we provided will be used as the getter function for the property vm.b
:
console.log(vm.b) // -> 2
vm.a = 2
console.log(vm.b) // -> 3
The value of vm.b
is always dependent on the value of vm.a
.
You can data-bind to computed properties in templates just like a normal property. Vue is aware that vm.b
depends on vm.a
, so it will update any bindings that depends on vm.b
when vm.a
changes.
Computed properties vs watch
template
<div id="demo">{{fullName}}</div>
watch example
var vm = new Vue({
el: '#demo',
data: {
firstName: 'Foo',
lastName: 'Bar',
fullName: 'Foo Bar'
}
})
vm.$watch('firstName', function (val) {
this.fullName = val + ' ' + this.lastName
})
vm.$watch('lastName', function (val) {
this.fullName = this.firstName + ' ' + val
})
Computed example
var vm = new Vue({
el: '#demo',
data: {
firstName: 'Foo',
lastName: 'Bar'
},
computed: {
fullName: function () {
return this.firstName + ' ' + this.lastName
}
}
})
Computed Setters
Computed properties will automatically be recomputed whenever any data on which the computation depends changes. However, if you need to manually change a computed property, Vue allows you to create a setter method to do this:
Template (from the basic example above):
<div id="example">
a={{ a }}, b={{ b }}
</div>
Javascript:
var vm = new Vue({
el: '#example',
data: {
a: 1
},
computed: {
b: {
// getter
get: function () {
return this.a + 1
},
// setter
set: function (newValue) {
this.a = newValue - 1
}
}
}
You can now invoke either the getter or the setter:
console.log(vm.b) // -> 2
vm.b = 4 // (setter)
console.log(vm.b) // -> 4
console.log(vm.a) // -> 3
vm.b = 4
will invoke the setter, and set this.a to 3; by extension, vm.b will evaluate to 4.
Using computed setters for v-model
You might need a v-model
on a computed property. Normally, the v-model won’t update the computed property value.
The template:
<div id="demo">
<div class='inline-block card'>
<div :class='{onlineMarker: true, online: status, offline: !status}'></div>
<p class='user-state'>User is {{ (status) ? 'online' : 'offline' }}</p>
</div>
<div class='margin-5'>
<input type='checkbox' v-model='status'>Toggle status (This will show you as offline to others)
</div>
</div>
Styling:
#demo {
font-family: Helvetica;
font-size: 12px;
}
.inline-block > * {
display: inline-block;
}
.card {
background: #ddd;
padding:2px 10px;
border-radius: 3px;
}
.onlineMarker {
width: 10px;
height: 10px;
border-radius: 50%;
transition: all 0.5s ease-out;
}
.online {
background-color: #3C3;
}
.offline {
background-color: #aaa;
}
.user-state {
text-transform: uppercase;
letter-spacing: 1px;
}
.margin-5 {
margin: 5px;
}
The component:
var demo = new Vue({
el: '#demo',
data: {
statusProxy: null
},
computed: {
status: {
get () {
return (this.statusProxy === null) ? true : this.statusProxy
}
}
}
})
fiddle Here you would see, clicking the radio button has no use at all, your status is still online.
var demo = new Vue({
el: '#demo',
data: {
statusProxy: null
},
computed: {
status: {
get () {
return (this.statusProxy === null) ? true : this.statusProxy
},
set (val) {
this.statusProxy = val
}
}
}
})
fiddle And now you can see the toggle happens as the checkbox is checked/unchecked.