[[📗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)