Skip to content

アプリを作ってみよう

商品リストを作ってみる

みなさんにはこの節の最後に Todo リストを作ってもらうのですが、商品リストをテーマに、Todo リストに必要な Vue の機能をピックアップしていきます。

こんな感じのを作っていきます。

必要な要素を考える

上の gif のようなアプリを実現するためには何が必要か考えてみましょう。

  • 商品リストのコンポーネントを作る
  • 商品のリストデータを保存する
  • 商品のリストデータを表示する
  • 商品を追加できる
  • 商品の値段が 500 円以上だったら赤くする
  • 商品の値段が 1000 円以上だったら「高額商品」と表示する

こんな感じでしょうか。
それでは上から順番に実装していきましょう。

商品リストのコンポーネントを作る

componentsディレクトリにItemList.vueというファイルを作成します。

src/components/ItemList.vue

中身はコンポーネントに最低限必要な部分だけ書きます。

vue
<script setup lang="ts"></script>

<template>
  <div>ItemList</div>
</template>

<style></style>

HelloWorld.vue

vue
<script setup lang="ts">
import ClickCounter from './ClickCounter.vue'
import ItemList from './ItemList.vue'

defineProps<{
  msg: string
}>()
</script>

<template>
  <div>
    <h1>{{ msg }}</h1>
    <ClickCounter />
    <ItemList />
  </div>
</template>

<style scoped>
a {
  color: #42b983;
}
</style>

表示されました。 こうすることで、後はItemList.vueの中身を書き変えればよくなります。

商品のリストデータを保存する

商品リストのデータを保存するのに適当な変数の型は何でしょうか?
商品「リスト」なので配列がよさそうです。
というわけで、配列を使ってデータを保持することにします。
今は商品の追加ができないので、とりあえずダミーデータを入れておきます。

参考: Array | MDN
参考:JavaScript オブジェクトの基本 - ウェブ開発を学ぶ | MDN

vue
<script setup lang="ts">
import { ref } from 'vue'

interface Item {
  name: string
  price: number
}

const items = ref<Item[]>([
  { name: 'たまご', price: 100 },
  { name: 'りんご', price: 160 }
])
</script>

<template>
  <div>ItemList</div>
</template>

<style></style>

4~7 行目は TypeScript の記法で、Itemという型をinterfaceを用いて定義しています。
そして ref のジェネリクスにItem[]を渡すことで、items変数をItem型の配列のrefとして扱えるようにしています。

参考:ジェネリクス (generics) | TypeScript 入門『サバイバル TypeScript』
参考:インターフェース (interface) | TypeScript 入門『サバイバル TypeScript』

商品のリストデータを表示する

先ほど定義したリストの情報を表示していきます。
Vue ではリストデータをtemplateタグ内で for 文のように書く v-for という構文があります。
v-for を使うときには:keyを設定しなければいけません(理由(やや難): 優先度 A: 必須 | Vue)。

参考: リストレンダリング | Vue

これを使ってデータを表示してみます。

vue
<template>
  <div>
    <div>ItemList</div>
    <ul>
      <li v-for="item in items" :key="item.name">
        <div>名前: {{ item.name }}</div>
        <div>{{ item.price }} 円</div>
      </li>
    </ul>
  </div>
</template>

表示できました。

商品を追加する

Vue では入力欄に入力された文字列とコンポーネントの変数を結びつけることができます。
参考: フォーム入力バインディング | Vue

これを使って商品を追加できるようにしてみます。

vue
<script setup lang="ts">
import { ref } from 'vue'

interface Item {
  name: string
  price: number
}

const items = ref<Item[]>([
  { name: 'たまご', price: 100 },
  { name: 'りんご', price: 160 }
])
const newItemName = ref('')
const newItemPrice = ref(0)

const addItem = () => {
  items.value.push({ name: newItemName.value, price: newItemPrice.value })
}
</script>

<template>
  <div>
    <div>ItemList</div>
    <ul>
      <li v-for="item in items" :key="item.name">
        <div>名前: {{ item.name }}</div>
        <div>{{ item.price }} 円</div>
      </li>
    </ul>
    <div>
      <label>
        名前
        <input v-model="newItemName" type="text" />
      </label>
      <label>
        価格
        <input v-model="newItemPrice" type="number" />
      </label>
      <button @click="addItem">追加</button>
    </div>
  </div>
</template>

<style></style>

参考: アロー関数式 | MDN

できました!

練習問題 1:商品リストに機能を追加

このままだとボタンを連打して商品の追加ができてしまいます。

  • ボタンを押したら入力欄を空にする機能
  • 入力欄が空だったらボタンを押しても追加されないようにする機能

を追加してみましょう。

商品の値段が 500 円以上だったら赤くする

Vue では、ある特定の条件が満たされたときに class を追加するという機構を持たせることできます。
これを使って、条件が満たされたときだけ CSS を当てるといったことができます。

参考: CSS の基本 | MDN
参考: クラスとスタイルのバインディング | Vue

vue
<template>
  <div>
    <div>ItemList</div>
    <ul>
      <li v-for="item in items" :key="item.name" :class="{ over500: item.price >= 500 }">
        <div>名前: {{ item.name }}</div>
        <div>{{ item.price }} 円</div>
      </li>
    </ul>
    <div>
      <label>
        名前
        <input v-model="newItemName" type="text" />
      </label>
      <label>
        価格
        <input v-model="newItemPrice" type="number" />
      </label>
      <button @click="addItem">add</button>
    </div>
  </div>
</template>

<style>
.over500 {
  color: red;
}
</style>

商品の値段が 10000 円以上だったら「高額商品」と表示する

Vue では、ある特定の条件を満たした場合のみ、対象コンポーネントを表示するという機能をv-ifという構文を使って実現できます。

参考: 条件付きレンダリング | Vue

これを使って商品の値段が 10000 円以上だったら「高額商品」と表示するという機能を実現してみましょう。

vue
<template>
  <div>
    <div>ItemList</div>
    <ul>
      <li v-for="item in items" :key="item.name" :class="{ over500: item.price >= 500 }">
        <div>名前: {{ item.name }}</div>
        <div>{{ item.price }} 円</div>
        <div v-if="item.price >= 10000">高額商品</div>
      </li>
    </ul>
    ==略==
  </div>
</template>

これで商品リストが完成しました!

今回の商品リストの全体像は以下のブランチに入っているので、参考にしてみてください。
traPtitech/naro-template-frontend at example/itemlist

Todo リストを作る

ここまで紹介してきた機能を使うことで Todo リストが作れるはずです。 頑張りましょう!

練習問題 2:Todo リストを作る

Todo リストを作りましょう。

必要な機能は以下の通りです。

  • タスクは未完または完了済みの状態を持つ。
  • タスクはタスク名を持つ。
  • 未完タスクのリストと完了済みタスクのリストが表示される。
  • タスクを完了させることができる。
  • タスクの追加ができる。

以上の機能が実現されていれば後は自由です。 スタイルが気になる人は CSS なども書きましょう。

一応作成例は以下のブランチに作ってみましたが、できるだけ自力で頑張ってみてください。分からないことなどあれば遠慮なく TA に質問してください。
traPtitech/naro-template-frontend at example/todolist