Skip to content

Commit 020627a

Browse files
authored
feat: content/1.vue/3.reactivity-2 (#30)
1 parent 596fc3e commit 020627a

File tree

3 files changed

+94
-24
lines changed

3 files changed

+94
-24
lines changed

Diff for: content/1.vue/3.reactivity-2/.template/files/app.vue

+28-8
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,38 @@
1-
<script setup>
2-
const count = ref(1)
3-
const doubled = computed(() => count.value * 2)
1+
<script setup lang="ts">
2+
let todoId = 1
3+
4+
const todoData = reactive({
5+
loading: false,
6+
data: null,
7+
})
48
59
function increment() {
6-
count.value++
10+
todoId++
11+
}
12+
13+
async function fetchTodo() {
14+
todoData.loading = true
15+
try {
16+
const res = await fetch(`https://jsonplaceholder.typicode.com/todos/${todoId}`)
17+
todoData.data = await res.json()
18+
}
19+
finally {
20+
todoData.loading = false
21+
}
722
}
23+
24+
watch(todoId, fetchTodo, { immediate: true })
825
</script>
926

1027
<template>
1128
<div>
12-
<p>count is {{ count }}</p>
13-
<p>doubled is {{ doubled }}</p>
14-
<button @click="increment">
15-
+1
29+
<p>ID: {{ todoId }}</p>
30+
<button type="button" :disabled="todoData.loading" @click="increment">
31+
次の TODO アイテムを取得
1632
</button>
33+
<p v-if="todoData.loading">
34+
Loading...
35+
</p>
36+
<pre v-else>{{ todoData.data }}</pre>
1737
</div>
1838
</template>
+28-14
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,39 @@
1-
<script setup>
2-
const count = ref(1)
3-
const multiplier = ref(2)
4-
const result = computed(() => count.value * multiplier.value)
1+
<script setup lang="ts">
2+
const todoData = reactive({
3+
id: 1,
4+
loading: false,
5+
data: null,
6+
})
57
68
function increment() {
7-
count.value++
9+
todoData.id++
810
}
9-
function multiply() {
10-
multiplier.value++
11+
12+
async function fetchTodo() {
13+
todoData.loading = true
14+
try {
15+
const res = await fetch(`https://jsonplaceholder.typicode.com/todos/${todoData.id}`)
16+
todoData.data = await res.json()
17+
}
18+
finally {
19+
todoData.loading = false
20+
}
1121
}
22+
23+
watch(() => todoData.id, fetchTodo, { immediate: true })
24+
25+
fetchTodo()
1226
</script>
1327

1428
<template>
1529
<div>
16-
<p>count is {{ count }}</p>
17-
<p>result is {{ result }}</p>
18-
<button @click="increment">
19-
+1
20-
</button>
21-
<button @click="multiply">
22-
x{{ multiplier }}
30+
<p>ID: {{ todoData.id }}</p>
31+
<button type="button" :disabled="todoData.loading" @click="increment">
32+
Next Todo
2333
</button>
34+
<p v-if="todoData.loading">
35+
Loading...
36+
</p>
37+
<pre v-else>{{ todoData.data }}</pre>
2438
</div>
2539
</template>

Diff for: content/1.vue/3.reactivity-2/index.md

+38-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,42 @@ ogImage: true
44

55
# Reactivity Part 2
66

7-
In the previous section, we learned about `ref` and `computed`. In this section, we will learn about `reactive` and `watch` that fullfills our basic needs for reactivity.
7+
前章で `ref` `computed` を使った基本的なデータバインディングを学びました。本章では、`reactive` `watch` について学びましょう。この章で基本的なリアクティビティシステムをマスターできます!
88

9-
// TODO:
9+
- [`reactive()`](https://ja.vuejs.org/api/reactivity-core#reactive) はオブジェクト全体をリアクティブなデータとして扱うことができます。複数のプロパティを持つオブジェクトを管理できます。
10+
11+
- [`watch()`](https://ja.vuejs.org/api/reactivity-core#watch) はリアクティブなデータの変化を監視し、変化があったときに特定の処理を実行することができます。
12+
13+
`reactive` で宣言された値は、JavaScript の[プロキシ](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Proxy)として返ってくるため、以下のように通常のオブジェクトと同じように操作することができます。
14+
15+
```ts
16+
const counter = reactive({ count: 0 })
17+
counter.count++ // .value は不要
18+
console.log(counter.count) // -> 1
19+
```
20+
21+
::note
22+
**注意**: よくある間違いとして、`ref` はプリミティブな値のみに対応し、オブジェクトには `reactive` を使うという誤解があります。実際は `ref` でも `ref({ count: 0 })` のようにオブジェクトをリアクティブな値として宣言することができます。
23+
また、`reactive` には[いくつかの制限事項がある](https://ja.vuejs.org/guide/essentials/reactivity-fundamentals#limitations-of-reactive)ため、リアクティブな状態を宣言する際は基本的に `ref` を用いるのが推奨されます。
24+
::
25+
26+
`watch``computed` と同様にリアクティブ値の変化に応じて作用しますが、主に `console.log``fetch` のような副作用をリアクティブに実行するときに使います。
27+
プレイグラウンドでは、サーバーで管理している TODO アイテムを表示していますが、表示する ID が変化したときに新しいアイテムを取得するために `watch` による監視をしています。
28+
29+
`watch` に関する詳しい説明は[ウォッチャーガイド](https://ja.vuejs.org/guide/essentials/watchers)を参照してください。
30+
31+
## チャレンジ問題
32+
33+
今のプレイグラウンドは、TODO アイテムに関するデータを `todoId``todoData` の二つのリアクティブ値として管理しています。これらを一つの `todoData` にまとめましょう。
34+
これらのステップを実行することで、`reactive``watch` の理解を深めることができるのでぜひ挑戦してみてください!
35+
36+
1. `todoData``id` プロパティを追加し、`todoId` を消しましょう。
37+
2. エラー箇所にしたがって、`todoId` と書いてある箇所を `todoData.id` に変えましょう。
38+
- これで `watch` 以外のエラーは解消されるはずです。
39+
3. `watch` の第一引数をゲッター関数に変えましょう。
40+
- `todoData.id` のままだと数値を渡していることになるため、`watch` が変化を補足できません。
41+
42+
もし手詰まりになったら、解決策を確認するためのボタンをクリックして、ヒントを得ることができます。
43+
:ButtonShowSolution{.bg-faded.px4.py2.rounded.border.border-base.hover:bg-active.hover:text-primary.hover:border-primary:50}
44+
45+
ここまでで Vue のリアクティビティシステムの基礎について学びました。次のステップで、Vue の強力な機能の一つである「Composition API」について学びましょう!

0 commit comments

Comments
 (0)