[[📗04 アットマークは耳マーク]] < [[📒Vue.jsクエスト]] > [[📗06 状態で広がるセカイ reactive編]]
## Abstract
何を作るにも必須といえる状態の制御を学び、作れるモノの幅を広げましょう。
## Lesson
[[Vue]]における状態は[[リアクティブ]]である必要があります。[[ref()]]で包むと変数を[[リアクティブ]]にできます。以下のコードは、ボタンを押すとカウントが増えていくプログラムです。
```html
<script setup lang="ts">
import { ref } from "vue";
const count = ref(0);
const handleClick = () => {
count.value += 1;
};
</script>
<template>
<div>{{ count }}</div>
<button @click="handleClick">Count up</button>
</template>
```
ポイントは2つあります。
### [[リアクティブ]]な変数`count`
`count`は`ref(...)`で包まれているので[[リアクティブ]]です。
```ts
const count = ref(0);
```
`count`が更新されるとそれをキャッチし、`<template>`内の`{{ count }}`が再描画されます。
### `Ref.value`による値の取得
ボタンがクリックされたらカウントしている部分があります。
```ts
const handleClick = () => {
count.value += 1;
};
```
`count += 1`でないことを不思議に思ったでしょうか。このような書き方になるのは、`ref(0)`の[[戻り値型]]は`number`ではなく`Ref<number>`になり、内部に`value`プロパティを持つためです。
```ts
export declare interface Ref<T = any> {
value: T;
[RefSymbol]: true;
}
```
なお、`<template>`内では明示的に`.value`する必要はありません。自動的にunwrapされるからです。
```ts
<div>{{ count }}</div>
```
## Missions
### Mission 1
#😁EASY
[[#Lesson]]のコードを『ボタンをクリックしたら値が2倍になる』よう改造してください。ただし初期値は`1`としてください。
%%
回答例
```html
<script setup lang="ts">
import { ref } from "vue";
const count = ref(1);
const handleClick = () => {
count.value *= 2;
};
</script>
<template>
<div>{{ count }}</div>
<button @click="handleClick">Count up</button>
</template>
```
%%
### Mission 2
#🙂NORMAL
`Click: 0`と書かれたボタンを押すたびに、ボタンの中の数字が1ずつ増えていくコードを書いてください。
%%
回答例
```html
<script setup lang="ts">
import { ref } from "vue";
const count = ref(0);
const increment = () => {
count.value += 1;
};
</script>
<template>
<button @click="increment">Click: {{ count }}</button>
</template>
```
%%
### Mission 3
#😵HARD
以下のプログラムを動くように書き直してください。ただし、以下の制約があるものとします。
- `<template>`で`.value`を使わない
- [[reactive()]]を使わない
```html
<script setup lang="ts">
import { ref } from "vue";
const countState = {
count: ref(1),
};
const handleClick = () => {
countState.count.value *= 2;
};
</script>
<template>
<div>{{ countState.count }}</div>
<div>NEXT: {{ countState.count * 2 }}</div>
<button @click="handleClick">Double up</button>
</template>
```
> [!hint]- Hint 1
> https://vuejs.org/guide/essentials/reactivity-fundamentals.html#ref-unwrapping-in-templates
%%
回答例
```html
<script setup lang="ts">
import { ref } from "vue";
const countState = {
count: ref(1),
};
const handleClick = () => {
countState.count.value *= 2;
};
const { count } = countState;
</script>
<template>
<div>{{ count }}</div>
<div>NEXT: {{ count * 2 }}</div>
<button @click="handleClick">Double up</button>
</template>
```
%%
## References
[Reactivity Fundamentals \| Vue\.js](https://vuejs.org/guide/essentials/reactivity-fundamentals.html)