Vue3 の基礎
リアクティビティー
近年、アプリは UI の利便性を求められることが多く、クライアント側だけで様々なデータを処理し、表示することの複雑さを要求されています。 そのため、アプリが持っているデータを表示し、そのデータが変更された場合も即時反映しなければならず、そういったロジックをフレームワークが受け持つようになりました。 詳しくは Vue 公式サイトのリアクティビティーの探求を一緒に見ていき、なぜリアクティビティーの理解が必要なのか、ここで理解しておきましょう。
データバインディング
HTML における input 要素とは、ユーザーから入力を受け付けることができる要素であり、その種類は 1 行のテキストから日付、数値、はもとより、チェックボックス、ラジオボタン、色(カラーピッカー UI)、日付(カレンダー UI)、レンジ(スライダー UI)などすべて input 要素が実現できます。
その input 要素の値を ref という関数が補足していることを確認してください。
const msg = ref("Hello World!");
<input v-model="msg" />
msgには常に、input 要素の変更された値が更新され続けています。その値msgは h1 要素に展開されていることがわかります。
<h1>{{ msg }}</h1>
では、アプリを少しづつ書いていきましょう。今回は買い物のメモをするアプリを想定します。
配列を表示する
<script setup>
import { ref } from 'vue'
const msg = ref('Hello World!')
const todos = ref(["卵", "キャベツ", "にんじん"]);
</script>
<template>
<h1>{{ msg }}</h1>
<ul>
<li v-for="todo in todos">
{{todo}}
</li>
</ul>
<input v-model="msg" />
</template>
todos内の配列は li 要素の for 文(v-for)によって処理されて表示されたと思います。
このように配列であれば Vue ではこのように書くことで簡単に表示されます。
入力に対応する
買い物項目を追加してみます。入力して追加ボタンが必要なので<button>要素を追加してみます。
そのままでは押しても何も起こらないので、ボタンを押されたときの処理を書きます。
<script setup>
import { ref } from 'vue'
const msg = ref("")
const todos = ref(["卵", "キャベツ", "にんじん"]);
</script>
<template>
<h1>{{msg}}</h1>
<ul>
<li v-for="todo in todos">
{{todo}}
</li>
</ul>
<input v-model="msg" />
<button @click="todos.push(msg)">追加</button>
</template>
button 要素の部分に注目すると、@click="todos.push(msg)"という処理が書かれています。
これはtodos配列に新しい項目であるmsgを一つ追加することを意味します。
試してみると、入力された新しい文字列が配列に追加されたことがわかると思います。
関数化する
これでもある程度期待する動作になったかと思いますが、input 要素内にテキストが残っていますね。ボタンを押したら消えてほしいです。 いくつか方法はありますが、こういった処理が複雑になってきたら script 内に関数としてまとめておきたいです。
<script setup>
import { ref } from 'vue'
const msg = ref("")
const todos = ref(["卵", "キャベツ", "にんじん"]);
const addedItem = () => {
todos.value.push(msg.value)
msg.value = ""
}
</script>
<template>
<h1>{{msg}}</h1>
<ul>
<li v-for="todo in todos">
{{todo}}
</li>
</ul>
<input v-model="msg" />
<button @click="addedItem">追加</button>
</template>
addedItemという関数が処理してくれるようになりました。
ただ、Vue Composition API の仕様で、<script>要素内でref関数で扱うデータにアクセスする場合はvalueプロパティを経由しなければならないということだけ注意してください。少し複雑になってきましたが、todosに push している処理の意味は先程と同じです。
msg.value = ""
によって、input 内のテキストが消えるようになりました。
これは補足しているmsgデータが空になった瞬間それを反映するリアクティビティの恩恵を受けています。
ボタンが押せないようにする
もしも input 要素が空のまま追加ボタンを押しても空の文字が入力されてしまいます。これはアプリとしては不具合になるので、制限をかけましょう。
button 要素にはdisabledという属性があります。これがあるとボタンは一時的に操作できなくなるのでこれを利用しましょう。
方法としては少しコードを足すだけで実現できます。
<script setup>
import { ref } from 'vue'
const msg = ref("")
const todos = ref(["卵", "キャベツ", "にんじん"]);
const addedItem = () => {
todos.value.push(msg.value)
msg.value = ""
}
</script>
<template>
<h1>{{msg}}</h1>
<ul>
<li v-for="todo in todos">
{{todo}}
</li>
</ul>
<input v-model="msg" />
<button :disabled="msg===''" @click="addedItem">追加</button>
</template>
ボタンに:disabled="msg===''"と入っています。disabled の冒頭に:が付いているのは Vue のルールです。値にブール値(真偽値)で disabled の true/false を指定するにはこのようにコロンをつけます、つけ忘れると、文字列の true/false がそのまま入ってしまいます。
msgの内容が空かどうかを判定して、disabled 属性を変更しています。すべてリアクティビティの恩恵です。