Skip to content

Commit fc2cf43

Browse files
committed
udpate computed properties
1 parent a52268d commit fc2cf43

File tree

1 file changed

+81
-21
lines changed

1 file changed

+81
-21
lines changed

source/guide/computed.md

Lines changed: 81 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,47 +5,107 @@ order: 8
55

66
Vue.js' inline expressions are very convenient, but the best use cases for them are simple boolean operations or string concatenations. For more complicated logic, you should use **computed properties**.
77

8-
In Vue.js, you define computed properties with the `computed` option:
8+
A computed property is used to declaratively describe a value that depends on other values. When you data-bind to a computed property inside the template, Vue knows when to update the DOM when any of the values depended upon by the computed property has changed. This can be very power and makes your code more declarative, data-driven and thus easier to maintain.
9+
10+
It is often a better idea to use a computed property rather than an imperative `$watch` callback. Consider this example:
11+
12+
``` html
13+
<div id="demo">{{fullName}}</div>
14+
```
15+
16+
``` js
17+
var vm = new Vue({
18+
data: {
19+
firstName: 'Foo',
20+
lastName: 'Bar',
21+
fullName: 'Foo Bar'
22+
}
23+
})
24+
25+
vm.$watch('firstName', function (val) {
26+
this.fullName = val + ' ' + this.lastName
27+
})
28+
29+
vm.$watch('lastName', function (val) {
30+
this.fullName = this.firstName + ' ' + val
31+
})
32+
```
33+
34+
The above code is imperative and cumbersome. Compare it with a computed property version:
935

1036
``` js
11-
var demo = new Vue({
37+
var vm = new Vue({
1238
data: {
1339
firstName: 'Foo',
1440
lastName: 'Bar'
1541
},
1642
computed: {
17-
fullName: {
18-
// the getter should return the desired value
19-
get: function () {
20-
return this.firstName + ' ' + this.lastName
21-
},
22-
// the setter is optional
23-
set: function (newValue) {
24-
var names = newValue.split(' ')
25-
this.firstName = names[0]
26-
this.lastName = names[names.length - 1]
27-
}
43+
fullName: function () {
44+
return this.firstName + ' ' + this.lastName
2845
}
2946
}
3047
})
31-
32-
demo.fullName // 'Foo Bar'
3348
```
3449

35-
When you only need the getter, you can provide a single function instead of an object:
50+
Much better. In addition, you can also provide a setter for a computed property:
3651

3752
``` js
3853
// ...
3954
computed: {
40-
fullName: function () {
41-
return this.firstName + ' ' + this.lastName
42-
}
55+
fullName: {
56+
// getter
57+
get: function () {
58+
return this.firstName + ' ' + this.lastName
59+
},
60+
// setter
61+
set: function (newValue) {
62+
var names = newValue.split(' ')
63+
this.firstName = names[0]
64+
this.lastName = names[names.length - 1]
65+
}
66+
}
4367
}
4468
// ...
4569
```
4670

47-
A computed property is essentially a property defined with getter/setter functions. You can use a computed property just like a normal property, but when you access it, you get the value returned by the getter function; when you change its value, you trigger the setter function passing in the new value as its argument.
71+
### Computed Poperty Caching
72+
73+
Before 0.12.8, computed properties behave just like getters - every time you access it, the getter function is re-evaluated. In 0.12.8 this has been improved - computed properties are cached and lazily re-evaluated only when one of its reactive dependencies have changed.
74+
75+
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 depend on A. Without caching, we'd be calling A's getter many more times than necessary and this could potentially cause performance issues. With caching, A's value will be cached as long as its dependencies haven't changed, and accessing it many times will not trigger unnecessary computations.
76+
77+
However, it is important to understand what is considered a "reactive dependency":
78+
79+
``` js
80+
var vm = new Vue({
81+
data: {
82+
msg: 'hi'
83+
},
84+
computed: {
85+
example: {
86+
return Date.now() + this.msg
87+
}
88+
}
89+
})
90+
```
91+
92+
In the example above, the computed property relies on `vm.msg`. Because this is an observed data property on the Vue instance, it is considered a reactive dependency. Whenever `vm.msg` is changed, `vm.example`'s value will be re-evaludated.
93+
94+
However, `Date.now()` is **not** a reactive dependency, because it has nothing to do with Vue's data observation system. Therefore, when you programatically access `vm.computed`, you will find the timestamp to remain the same unless `vm.msg` triggered a re-evaluation.
95+
96+
Sometimes you may want to preserve the simple getter-like behavior, where every time you access `vm.example` it is simply re-evaluated. Starting in 0.12.11, it's possible to turn off caching for a specific computed property:
97+
98+
``` js
99+
computed: {
100+
example: {
101+
cache: false,
102+
get: function () {
103+
return Date.now() + this.msg
104+
}
105+
}
106+
}
107+
```
48108

49-
Before 0.12.8, computed properties behave just like getters - every time you access it, the getter function is re-evaluated. In 0.12.8 this has been improved - computed properties are cached and lazily re-evaluated only when necessary.
109+
Now, every time you access `vm.example`, the timestamp will be up-to-date. However, note this only affects programmatic access inside JavaScript; data-bindings are still dependency-drive. When you bind to a computed property in the template as {% raw %}`{{example}}`{% endraw %}, the DOM will only be updated when a reactive dependency has changed.
50110

51111
Next, let's learn about how to [write a custom directive](/guide/custom-directive.html).

0 commit comments

Comments
 (0)