Skip to content

Commit

Permalink
translate guide/essentials/computed.md (#304)
Browse files Browse the repository at this point in the history
  • Loading branch information
mgr-kb authored Mar 2, 2022
1 parent bbe7dd9 commit 06fd0cd
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 47 deletions.
2 changes: 1 addition & 1 deletion .vitepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ export const sidebar = {
link: '/guide/essentials/reactivity-fundamentals'
},
{
text: 'Computed Properties',
text: '算出プロパティ',
link: '/guide/essentials/computed'
},
{
Expand Down
2 changes: 1 addition & 1 deletion .vitepress/theme/components/VueSchoolLink.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
rel="sponsored noopener"
:title="title"
>
<slot>Watch a free video lesson on Vue School</slot>
<slot>Vue School の無料動画レッスンを見る</slot>
</a>
</div>
</template>
Expand Down
90 changes: 45 additions & 45 deletions src/guide/essentials/computed.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
# Computed Properties
# 算出プロパティ

<div class="options-api">
<VueSchoolLink href="https://vueschool.io/lessons/computed-properties-in-vue-3" title="Free Vue.js Computed Properties Lesson"/>
<VueSchoolLink href="https://vueschool.io/lessons/computed-properties-in-vue-3" title="Vue School の算出プロパティの無料動画レッスン"/>
</div>

<div class="composition-api">
<VueSchoolLink href="https://vueschool.io/lessons/vue-fundamentals-capi-computed-properties-in-vue-with-the-composition-api" title="Free Vue.js Computed Properties Lesson"/>
<VueSchoolLink href="https://vueschool.io/lessons/vue-fundamentals-capi-computed-properties-in-vue-with-the-composition-api" title="Vue School の算出プロパティの無料動画レッスン"/>
</div>

## Basic Example
## 基本的な例

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, if we have an object with a nested array:
テンプレート内に式を書けるのはとても便利ですが、非常に簡単な操作しかできません。テンプレート内に多くのロジックを詰め込むと、コードが肥大化し、メンテナンスが難しくなります。例えば、配列が入れ子になっているオブジェクトがあった場合:

<div class="options-api">

Expand Down Expand Up @@ -47,16 +47,16 @@ const author = reactive({

</div>

And we want to display different messages depending on if `author` already has some books or not:
そして、`author` がすでにいくつかの `books` を持っているかどうかによって、異なるメッセージを表示したいとします:

```vue-html
<p>Has published books:</p>
<span>{{ author.books.length > 0 ? 'Yes' : 'No' }}</span>
```

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.
この時点で、テンプレートが少しごちゃごちゃしてきました。しばらく眺めて、やっとこれが `author.books` に依存した計算をしていることに気づくでしょう。さらに重要なことは、同じ計算をテンプレートの中で複数回使う場合、おそらく繰り返して使いたくはないでしょう。

That's why for complex logic that includes reactive data, it is recommended to use a **computed property**. Here's the same example, refactored:
上記の理由から、リアクティブなデータを含む複雑なロジックには**算出プロパティ**を使用すべきです。以下は上記と同じ例をリファクタリングしたものです:

<div class="options-api">

Expand All @@ -75,9 +75,9 @@ export default {
}
},
computed: {
// a computed getter
// 算出プロパティの getter 関数
publishedBooksMessage() {
// `this` points to the component instance
// `this` はコンポーネントのインスタンスを指します
return this.author.books.length > 0 ? 'Yes' : 'No'
}
}
Expand All @@ -89,15 +89,15 @@ export default {
<span>{{ publishedBooksMessage }}</span>
```

[Try it in the Playground](https://sfc.vuejs.org/#eyJBcHAudnVlIjoiPHNjcmlwdD5cbmV4cG9ydCBkZWZhdWx0IHtcbiAgZGF0YSgpIHtcbiAgICByZXR1cm4ge1xuICAgICAgYXV0aG9yOiB7XG4gICAgICAgIG5hbWU6ICdKb2huIERvZScsXG4gICAgICAgIGJvb2tzOiBbXG4gICAgICAgICAgJ1Z1ZSAyIC0gQWR2YW5jZWQgR3VpZGUnLFxuICAgICAgICAgICdWdWUgMyAtIEJhc2ljIEd1aWRlJyxcbiAgICAgICAgICAnVnVlIDQgLSBUaGUgTXlzdGVyeSdcbiAgICAgICAgXVxuICAgICAgfVxuICAgIH1cbiAgfSxcbiAgY29tcHV0ZWQ6IHtcbiAgICBwdWJsaXNoZWRCb29rc01lc3NhZ2UoKSB7XG4gICAgICByZXR1cm4gdGhpcy5hdXRob3IuYm9va3MubGVuZ3RoID4gMCA/ICdZZXMnIDogJ05vJ1xuICAgIH1cbiAgfVxufVxuPC9zY3JpcHQ+XG5cbjx0ZW1wbGF0ZT5cbiAgPHA+SGFzIHB1Ymxpc2hlZCBib29rczo8L3A+XG4gIDxzcGFuPnt7IGF1dGhvci5ib29rcy5sZW5ndGggPiAwID8gJ1llcycgOiAnTm8nIH19PC9zcGFuPlxuPC90ZW1wbGF0ZT4iLCJpbXBvcnQtbWFwLmpzb24iOiJ7XG4gIFwiaW1wb3J0c1wiOiB7XG4gICAgXCJ2dWVcIjogXCJodHRwczovL3NmYy52dWVqcy5vcmcvdnVlLnJ1bnRpbWUuZXNtLWJyb3dzZXIuanNcIlxuICB9XG59In0=)
[プレイグラウンドで試す](https://sfc.vuejs.org/#eyJBcHAudnVlIjoiPHNjcmlwdD5cbmV4cG9ydCBkZWZhdWx0IHtcbiAgZGF0YSgpIHtcbiAgICByZXR1cm4ge1xuICAgICAgYXV0aG9yOiB7XG4gICAgICAgIG5hbWU6ICdKb2huIERvZScsXG4gICAgICAgIGJvb2tzOiBbXG4gICAgICAgICAgJ1Z1ZSAyIC0gQWR2YW5jZWQgR3VpZGUnLFxuICAgICAgICAgICdWdWUgMyAtIEJhc2ljIEd1aWRlJyxcbiAgICAgICAgICAnVnVlIDQgLSBUaGUgTXlzdGVyeSdcbiAgICAgICAgXVxuICAgICAgfVxuICAgIH1cbiAgfSxcbiAgY29tcHV0ZWQ6IHtcbiAgICBwdWJsaXNoZWRCb29rc01lc3NhZ2UoKSB7XG4gICAgICByZXR1cm4gdGhpcy5hdXRob3IuYm9va3MubGVuZ3RoID4gMCA/ICdZZXMnIDogJ05vJ1xuICAgIH1cbiAgfVxufVxuPC9zY3JpcHQ+XG5cbjx0ZW1wbGF0ZT5cbiAgPHA+SGFzIHB1Ymxpc2hlZCBib29rczo8L3A+XG4gIDxzcGFuPnt7IGF1dGhvci5ib29rcy5sZW5ndGggPiAwID8gJ1llcycgOiAnTm8nIH19PC9zcGFuPlxuPC90ZW1wbGF0ZT4iLCJpbXBvcnQtbWFwLmpzb24iOiJ7XG4gIFwiaW1wb3J0c1wiOiB7XG4gICAgXCJ2dWVcIjogXCJodHRwczovL3NmYy52dWVqcy5vcmcvdnVlLnJ1bnRpbWUuZXNtLWJyb3dzZXIuanNcIlxuICB9XG59In0=)

Here we have declared a computed property `publishedBooksMessage`.
ここでは、`publishedBooksMessage` という算出プロパティを宣言しています。

Try to change the value of the `books` array in the application `data` and you will see how `publishedBooksMessage` is changing accordingly.
アプリケーションの `data` プロパティ内の `books` 配列の値を変更してみると、それに応じて `publishedBooksMessage` の結果がどのように変化しているかがわかります。

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 `this.publishedBooksMessage` when `this.author.books` changes.
通常のプロパティと同じように、テンプレート内の算出プロパティにデータバインドすることもできます。Vue `this.publishedBooksMessage` `this.author.books` に依存していることを知っているので、`this.author.books` が変わると `this.publishedBooksMessage` に依存する全てのバインディングを更新します。

See also: [Typing Computed Properties](/guide/typescript/options-api.html#typing-computed-properties) <sup class="vt-badge ts" />
参照: [Typing Computed Properties](/guide/typescript/options-api.html#typing-computed-properties) <sup class="vt-badge ts" />

</div>

Expand All @@ -116,7 +116,7 @@ const author = reactive({
]
})
// a computed ref
// 算出プロパティの参照
const publishedBooksMessage = computed(() => {
return author.books.length > 0 ? 'Yes' : 'No'
})
Expand All @@ -128,19 +128,19 @@ const publishedBooksMessage = computed(() => {
</template>
```

[Try it in the Playground](https://sfc.vuejs.org/#eyJBcHAudnVlIjoiPHNjcmlwdCBzZXR1cD5cbmltcG9ydCB7IHJlYWN0aXZlLCBjb21wdXRlZCB9IGZyb20gJ3Z1ZSdcblxuY29uc3QgYXV0aG9yID0gcmVhY3RpdmUoe1xuICBuYW1lOiAnSm9obiBEb2UnLFxuICBib29rczogW1xuICAgICdWdWUgMiAtIEFkdmFuY2VkIEd1aWRlJyxcbiAgICAnVnVlIDMgLSBCYXNpYyBHdWlkZScsXG4gICAgJ1Z1ZSA0IC0gVGhlIE15c3RlcnknXG4gIF1cbn0pXG5cbi8vIGEgY29tcHV0ZWQgcmVmXG5jb25zdCBwdWJsaXNoZWRCb29rc01lc3NhZ2UgPSBjb21wdXRlZCgoKSA9PiB7XG4gIHJldHVybiBhdXRob3IuYm9va3MubGVuZ3RoID4gMCA/ICdZZXMnIDogJ05vJ1xufSlcbjwvc2NyaXB0PlxuXG48dGVtcGxhdGU+XG4gIDxwPkhhcyBwdWJsaXNoZWQgYm9va3M6PC9wPlxuICA8c3Bhbj57eyBwdWJsaXNoZWRCb29rc01lc3NhZ2UgfX08L3NwYW4+XG48L3RlbXBsYXRlPiIsImltcG9ydC1tYXAuanNvbiI6IntcbiAgXCJpbXBvcnRzXCI6IHtcbiAgICBcInZ1ZVwiOiBcImh0dHBzOi8vc2ZjLnZ1ZWpzLm9yZy92dWUucnVudGltZS5lc20tYnJvd3Nlci5qc1wiXG4gIH1cbn0ifQ==)
[プレイグラウンドで試す](https://sfc.vuejs.org/#eyJBcHAudnVlIjoiPHNjcmlwdCBzZXR1cD5cbmltcG9ydCB7IHJlYWN0aXZlLCBjb21wdXRlZCB9IGZyb20gJ3Z1ZSdcblxuY29uc3QgYXV0aG9yID0gcmVhY3RpdmUoe1xuICBuYW1lOiAnSm9obiBEb2UnLFxuICBib29rczogW1xuICAgICdWdWUgMiAtIEFkdmFuY2VkIEd1aWRlJyxcbiAgICAnVnVlIDMgLSBCYXNpYyBHdWlkZScsXG4gICAgJ1Z1ZSA0IC0gVGhlIE15c3RlcnknXG4gIF1cbn0pXG5cbi8vIGEgY29tcHV0ZWQgcmVmXG5jb25zdCBwdWJsaXNoZWRCb29rc01lc3NhZ2UgPSBjb21wdXRlZCgoKSA9PiB7XG4gIHJldHVybiBhdXRob3IuYm9va3MubGVuZ3RoID4gMCA/ICdZZXMnIDogJ05vJ1xufSlcbjwvc2NyaXB0PlxuXG48dGVtcGxhdGU+XG4gIDxwPkhhcyBwdWJsaXNoZWQgYm9va3M6PC9wPlxuICA8c3Bhbj57eyBwdWJsaXNoZWRCb29rc01lc3NhZ2UgfX08L3NwYW4+XG48L3RlbXBsYXRlPiIsImltcG9ydC1tYXAuanNvbiI6IntcbiAgXCJpbXBvcnRzXCI6IHtcbiAgICBcInZ1ZVwiOiBcImh0dHBzOi8vc2ZjLnZ1ZWpzLm9yZy92dWUucnVudGltZS5lc20tYnJvd3Nlci5qc1wiXG4gIH1cbn0ifQ==)

Here we have declared a computed property `publishedBooksMessage`. The `computed()` function expects to be passed a getter function, and the 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.
ここでは、`publishedBooksMessage` という算出プロパティを宣言しています。`computed()` 関数は getter 関数が渡されることを想定しており、返り値は **算出された ref** となります。通常の ref と同様に、`publishedBooksMessage.value` で算出結果を参照することができます。また、算出結果はテンプレート内では自動的にアンラップされるため、テンプレート内では `.value` なしで参照することができます。

A computed property automatically tracks its reactive dependencies. Vue is aware that the computation of `publishedBooksMessage` depends on `author.books`, so it will update any bindings that depend on `publishedBooksMessage` when `author.books` changes.
算出プロパティは、自動的にリアクティブな依存関係を追跡します。Vue `publishedBooksMessage` の算出が `author.books` に依存することを知っているので、`author.books` が変わると `publishedBooksMessage` に依存する全てのバインディングを更新します。

See also: [Typing Computed](/guide/typescript/composition-api.html#typing-computed) <sup class="vt-badge ts" />
参考: [Typing Computed](/guide/typescript/composition-api.html#typing-computed) <sup class="vt-badge ts" />

</div>

## Computed Caching vs Methods
## 算出プロパティ vs メソッド

You may have noticed we can achieve the same result by invoking a method in the expression:
こういった式を持つメソッドを呼び出すことで、同じ結果が実現できることに気付いたかもしれません:

```vue-html
<p>{{ calculateBooksMessage() }}</p>
Expand All @@ -149,7 +149,7 @@ You may have noticed we can achieve the same result by invoking a method in the
<div class="options-api">

```js
// in component
// コンポーネント内
methods: {
calculateBooksMessage() {
return this.author.books.length > 0 ? 'Yes' : 'No'
Expand All @@ -162,17 +162,17 @@ methods: {
<div class="composition-api">

```js
// in component
// コンポーネント内
function calculateBooksMessage() {
return author.books.length > 0 ? 'Yes' : 'No'
}
```

</div>

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 `publishedBooksMessage` will immediately return the previously computed result without having to run the getter function again.
算出プロパティの代わりに、同じような関数をメソッドとして定義することもできます。最終的には、2 つのアプローチは完全に同じ結果になります。しかしながら、**算出プロパティはリアクティブな依存関係にもとづきキャッシュされる**という違いがあります。算出プロパティは、リアクティブな依存関係が更新されたときにだけ再評価されます。これはつまり、 `author.books` が変わらない限りは、`publishedBooksMessage` に何度アクセスしても、getter 関数を再び実行することなく、以前計算された結果を即時に返すということです。

This also means the following computed property will never update, because `Date.now()` is not a reactive dependency:
`Date.now()` はリアクティブな依存ではないため、次の算出プロパティは二度と更新されないことを意味します:

<div class="options-api">

Expand All @@ -194,13 +194,13 @@ const now = computed(() => Date.now())

</div>

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 `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.
なぜキャッシングが必要なのでしょうか?巨大な配列をループしたり多くの計算を必要とする、コストの高い `list` という算出プロパティがあることを想像してみてください。`list` に依存する他の算出プロパティもあるかもしれません。その場合、キャッシングがなければ必要以上に `list`getter を実行することになってしまいます。キャッシングしたくない場合は、代わりにメソッドを使いましょう。

## Writable Computed
## 書き込み可能な 算出関数

Computed properties are by default getter-only. If you attempt to assign a new value to a computed property, you will receive a runtime warning. In the rare cases where you need a "writable" computed property, you can create one by providing both a getter and a setter:
算出プロパティは、デフォルトでは getter 関数のみです。算出プロパティに新しい値を代入しようとすると、ランタイム警告が表示されます。まれに「書き込み可能な」算出プロパティが必要な場合があります。その場合は getter 関数と setter 関数の両方を提供することで、それを作成することができます:

<div class="options-api">

Expand All @@ -214,21 +214,21 @@ export default {
},
computed: {
fullName: {
// getter
// getter 関数
get() {
return this.firstName + ' ' + this.lastName
},
// setter
// setter 関数
set(newValue) {
// Note: we are using destructuring assignment syntax here.
[this.firstName, this.lastName] = newValue.split(' ')
// 注意: ここでは、破壊的な代入構文を使用しています。
;[this.firstName, this.lastName] = newValue.split(' ')
}
}
}
}
```

Now when you run `this.fullName = 'John Doe'`, the setter will be invoked and `this.firstName` and `this.lastName` will be updated accordingly.
`this.fullName = 'John Doe'` を呼ぶと、setter 関数が呼び出され、`this.firstName` `this.lastName` が適切に更新されます。

</div>

Expand All @@ -242,29 +242,29 @@ const firstName = ref('John')
const lastName = ref('Doe')
const fullName = computed({
// getter
// getter 関数
get() {
return firstName.value + ' ' + lastName.value
},
// setter
// setter 関数
set(newValue) {
// Note: we are using destructuring assignment syntax here.
[firstName.value, lastName.value] = newValue.split(' ')
// 注意: ここでは、破壊的な代入構文を使用しています。
;[firstName.value, lastName.value] = newValue.split(' ')
}
})
</script>
```

Now when you run `fullName.value = 'John Doe'`, the setter will be invoked and `firstName` and `lastName` will be updated accordingly.
`fullName = 'John Doe'` を呼ぶと、setter 関数が呼び出され、`firstName` `lastName` が適切に更新されます。

</div>

## Best Practices
## ベストプラクティス

### Getters should be side-effect free
### getter 関数は副作用のないものでなければならない

It is important to remember that computed getter functions should only perform pure computation and be free of side effects. For example, don't make async requests or mutate the DOM inside a computed getter! Think of a computed property as declaratively describing how to derive a value based on other values - its only responsibility should be computing and returning that value. Later in the guide we will discuss how we can perform side effects in reaction to state changes with [watchers](./watchers).
算出プロパティにおける getter 関数は計算のみを行い、副作用がないようにすることが重要です。例えば、非同期リクエストや、DOM を変化させないようにしましょう!算出プロパティは他の値に基づいて計算する方法を宣言的に記述していると考えてください。その唯一の責任は、値を計算して返すことでなければなりません。このガイドの後半では、 [ウォッチャー](./watchers) を使って、状態の変化に反応して副作用を実行する方法について説明します。

### Avoid mutating computed value
### 算出した値の変更を避ける

The returned value from a computed property is derived state. Think of it as a temporary snapshot - every time the source state changes, a new snapshot is created. It does not make sense to mutate a snapshot, so a computed return value should be treated as read-only and never be mutated - instead, update the source state it depends on to trigger new computations.
算出プロパティから返る値は、派生され状態です。一時的なスナップショットとして考えてください。ソースの状態が変わるたびに、新しいスナップショットが作成されます。スナップショットの値を変更することは意味がないため、計算された結果は読み取り専用として扱い、変更しないようにします。その代わり、新しい計算結果が必要な場合は、依存するソースの状態を更新します。

0 comments on commit 06fd0cd

Please sign in to comment.