You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
At this point, the template is no longer simple and declarative. You have to look at it for a second before realizing that it performs a calculation depending on `author.books`. The problem is made worse when you want to include this calculation in your template more than once.
49
+
At this point, the template is getting a bit cluttered. We have to look at it for a second before realizing that it performs a calculation depending on `author.books`. More importantly, we probably don't want to repeat ourselves if we need to include this calculation in the template more than once.
52
50
53
-
That's why for complex logic that includes reactive data, you should use a **computed property**. Here's the same example, refactored:
51
+
That's why for complex logic that includes reactive data, it is recommended to use a **computed property**. Here's the same example, refactored:
[Try it in the Playground](https://sfc.vuejs.org/#eyJBcHAudnVlIjoiPHNjcmlwdD5cbmV4cG9ydCBkZWZhdWx0IHtcbiAgZGF0YSgpIHtcbiAgICByZXR1cm4ge1xuICAgICAgYXV0aG9yOiB7XG4gICAgICAgIG5hbWU6ICdKb2huIERvZScsXG4gICAgICAgIGJvb2tzOiBbXG4gICAgICAgICAgJ1Z1ZSAyIC0gQWR2YW5jZWQgR3VpZGUnLFxuICAgICAgICAgICdWdWUgMyAtIEJhc2ljIEd1aWRlJyxcbiAgICAgICAgICAnVnVlIDQgLSBUaGUgTXlzdGVyeSdcbiAgICAgICAgXVxuICAgICAgfVxuICAgIH1cbiAgfSxcbiAgY29tcHV0ZWQ6IHtcbiAgICBwdWJsaXNoZWRCb29rc01lc3NhZ2UoKSB7XG4gICAgICByZXR1cm4gdGhpcy5hdXRob3IuYm9va3MubGVuZ3RoID4gMCA/ICdZZXMnIDogJ05vJ1xuICAgIH1cbiAgfVxufVxuPC9zY3JpcHQ+XG5cbjx0ZW1wbGF0ZT5cbiAgPHA+SGFzIHB1Ymxpc2hlZCBib29rczo8L3A+XG4gIDxzcGFuPnt7IGF1dGhvci5ib29rcy5sZW5ndGggPiAwID8gJ1llcycgOiAnTm8nIH19PC9zcGFuPlxuPC90ZW1wbGF0ZT4iLCJpbXBvcnQtbWFwLmpzb24iOiJ7XG4gIFwiaW1wb3J0c1wiOiB7XG4gICAgXCJ2dWVcIjogXCJodHRwczovL3NmYy52dWVqcy5vcmcvdnVlLnJ1bnRpbWUuZXNtLWJyb3dzZXIuanNcIlxuICB9XG59In0=)
89
85
90
86
Here we have declared a computed property `publishedBooksMessage`.
91
87
92
88
Try to change the value of `books` array in the application `data` and you will see how `publishedBooksMessage` is changing accordingly.
93
89
94
-
You can data-bind to computed properties in templates just like a normal property. Vue is aware that `vm.publishedBooksMessage` depends on `vm.author.books`, so it will update any bindings that depend on `vm.publishedBooksMessage` when `vm.author.books` 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.
90
+
You can data-bind to computed properties in templates just like a normal property. Vue is aware that `this.publishedBooksMessage` depends on `this.author.books`, so it will update any bindings that depend on `vm.publishedBooksMessage` when `this.author.books` 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.
[Try it in the Playground](https://sfc.vuejs.org/#eyJBcHAudnVlIjoiPHNjcmlwdCBzZXR1cD5cbmltcG9ydCB7IHJlZiwgY29tcHV0ZWQgfSBmcm9tICd2dWUnXG5cbmNvbnN0IGF1dGhvciA9IHJlZih7XG4gIG5hbWU6ICdKb2huIERvZScsXG4gIGJvb2tzOiBbXG4gICAgJ1Z1ZSAyIC0gQWR2YW5jZWQgR3VpZGUnLFxuICAgICdWdWUgMyAtIEJhc2ljIEd1aWRlJyxcbiAgICAnVnVlIDQgLSBUaGUgTXlzdGVyeSdcbiAgXVxufSlcblxuLy8gYSBjb21wdXRlZCByZWZcbmNvbnN0IHB1Ymxpc2hlZEJvb2tzTWVzc2FnZSA9IGNvbXB1dGVkKCgpID0+IHtcbiAgcmV0dXJuIGF1dGhvci52YWx1ZS5ib29rcy5sZW5ndGggPiAwID8gJ1llcycgOiAnTm8nXG59KVxuPC9zY3JpcHQ+XG5cbjx0ZW1wbGF0ZT5cbiAgPHA+SGFzIHB1Ymxpc2hlZCBib29rczo8L3A+XG4gIDxzcGFuPnt7IHB1Ymxpc2hlZEJvb2tzTWVzc2FnZSB9fTwvc3Bhbj5cbjwvdGVtcGxhdGU+IiwiaW1wb3J0LW1hcC5qc29uIjoie1xuICBcImltcG9ydHNcIjoge1xuICAgIFwidnVlXCI6IFwiaHR0cHM6Ly9zZmMudnVlanMub3JnL3Z1ZS5ydW50aW1lLmVzbS1icm93c2VyLmpzXCJcbiAgfVxufSJ9)
122
+
123
+
Here we have declared a computed property `publishedBooksMessage`. The `computed()` method expects a getter function, and returned value is a **computed ref**. Similar to normal refs, you can access the computed result as `publishedBooksMessage.value`. Computed refs are also auto-unwrapped in templates so you can reference them without `.value` in template expressions.
124
+
125
+
Vue is aware that the computation of `publishedBooksMessage` depends on `author.value.books`, so it will update any bindings that depend on `publishedBooksMessage` when `author.value.books` 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.
126
+
127
+
</div>
95
128
96
129
## Computed Caching vs Methods
97
130
@@ -101,6 +134,8 @@ You may have noticed we can achieve the same result by invoking a method in the
101
134
<p>{{ calculateBooksMessage() }}</p>
102
135
```
103
136
137
+
<divclass="options-api">
138
+
104
139
```js
105
140
// in component
106
141
methods: {
@@ -110,154 +145,104 @@ methods: {
110
145
}
111
146
```
112
147
113
-
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 `author.books` has not changed, multiple access to the `publishedBooksMessage` computed property will immediately return the previously computed result without having to run the function again.
148
+
</div>
114
149
115
-
This also means the following computed property will never update, because `Date.now()` is not a reactive dependency:
150
+
<divclass="composition-api">
116
151
117
152
```js
118
-
computed: {
119
-
now() {
120
-
returnDate.now()
121
-
}
153
+
// in component
154
+
functioncalculateBooksMessage() {
155
+
returnauthor.value.books.length>0?'Yes':'No'
122
156
}
123
157
```
124
158
125
-
In comparison, a method invocation will **always** run the function whenever a re-render happens.
159
+
</div>
126
160
127
-
Why do we need caching? Imagine we have an expensive computed property `list`, 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 `list`. Without caching, we would be executing `list`’s getter many more times than necessary! In cases where you do not want caching, use a `method` instead.
161
+
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 <codeclass="options-api">author.books</code><codeclass="composition-api">author.value.books</code> has not changed, multiple access to `publishedBooksMessage` will immediately return the previously computed result without having to run the getter function again.
128
162
129
-
## Writable Computed
163
+
This also means the following computed property will never update, because `Date.now()` is not a reactive dependency:
130
164
131
-
Computed properties are by default getter-only, but you can also provide a setter when you need it:
165
+
<divclass="options-api">
132
166
133
167
```js
134
-
// ...
135
168
computed: {
136
-
fullName: {
137
-
// getter
138
-
get() {
139
-
returnthis.firstName+''+this.lastName
140
-
},
141
-
// setter
142
-
set(newValue) {
143
-
constnames=newValue.split('')
144
-
this.firstName= names[0]
145
-
this.lastName= names[names.length-1]
146
-
}
169
+
now() {
170
+
returnDate.now()
147
171
}
148
172
}
149
-
// ...
150
173
```
151
174
152
-
Now when you run `vm.fullName = 'John Doe'`, the setter will be invoked and `vm.firstName` and `vm.lastName` will be updated accordingly.
153
-
154
-
## Watchers
155
-
156
-
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.
157
-
158
-
For example:
159
-
160
-
```vue-html
161
-
<div id="watch-example">
162
-
<p>
163
-
Ask a yes/no question:
164
-
<input v-model="question" />
165
-
</p>
166
-
<p>{{ answer }}</p>
167
175
</div>
168
-
```
169
176
170
-
```vue-html
171
-
<!-- Since there is already a rich ecosystem of ajax libraries -->
172
-
<!-- and collections of general-purpose utility methods, Vue core -->
173
-
<!-- is able to remain small by not reinventing them. This also -->
174
-
<!-- gives you the freedom to use what you're familiar with. -->
In this case, using the `watch` option allows us to perform an asynchronous operation (accessing an API) and sets a condition for performing this operation. None of that would be possible with a computed property.
185
+
In comparison, a method invocation will **always** run the function whenever a re-render happens.
214
186
215
-
In addition to the `watch` option, you can also use the imperative [vm.$watch API](/api/component-instance.html#watch).
187
+
Why do we need caching? Imagine we have an expensive computed property `list`, 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 `list`. Without caching, we would be executing `list`’s getter many more times than necessary! In cases where you do not want caching, use a method call instead.
216
188
217
-
### Computed vs Watched Property
189
+
##Writable Computed
218
190
219
-
Vue does provide a more generic way to observe and react to data changes on a current active 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:
191
+
Computed properties are by default getter-only. When you attempt to mutate a computed property, you will receive a runtime warning. But you can provide a setter to create a "writable" computed property if you need to:
220
192
221
-
```vue-html
222
-
<div id="demo">{{ fullName }}</div>
223
-
```
193
+
<divclass="options-api">
224
194
225
195
```js
226
-
constvm=Vue.createApp({
196
+
exportdefault{
227
197
data() {
228
198
return {
229
-
firstName:'Foo',
230
-
lastName:'Bar',
231
-
fullName:'Foo Bar'
199
+
firstName:'John',
200
+
lastName:'Doe'
232
201
}
233
202
},
234
-
watch: {
235
-
firstName(val) {
236
-
this.fullName= val +''+this.lastName
237
-
},
238
-
lastName(val) {
239
-
this.fullName=this.firstName+''+ val
203
+
computed: {
204
+
fullName: {
205
+
// getter
206
+
get() {
207
+
returnthis.firstName+''+this.lastName
208
+
},
209
+
// setter
210
+
set(newValue) {
211
+
// Note: we are using destructuring assignment syntax here.
0 commit comments