0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【TypeScript&Nuxt.js】占いアプリ②カードを引く関数を作る

Posted at

前回はこちら

進め方

  1. タロットカードのデータをTypeScriptで配列にする ✅
  2. その中からランダムに1枚選ぶロジックを書く 👈今回はこれ
  3. 結果を表示する画面を作る(1ページ)
  4. カードごとに画像を表示してみる
  5. NuxtLinkでページ遷移(トップ→結果ページ)
  6. デザインを整える
  7. 応用:今日の運勢APIを取り入れてみる
  8. データの組み合わせで文章を作る

ステップ2.用意したカードの中からランダムに1枚選ぶロジックを書く

ざっと雛形。

<template>
  <div class="p-fortune-contents">
    <h1>タロット占い🔮</h1>
    <button @click="drawCard">カードを引く</button>

    <div class="p-results">
      <h2>今日の運勢</h2>
      <div class="p-results-card">
        <p>カードの番号</p>
        <p>カードの名前</p>
        <p>カードの内容</p>
      </div>
    </div>
  </div>
</template>

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

<style scoped>
</style>

「今日の運勢」の下に引いたタロットカードの情報を入れたい。→refを使う!

▼refの型付け

TSでrefを使うので、下記の公式ドキュメントの【refの型付け】を参考にする。

自分で考えて書いてみたが、GPTに聞いたら修正箇所の指摘が入った。

// 間違い
const selectedCard: Ref<number | string > = ref(null)

// ↓

// 修正後
const selectedCard: Ref<number | string | null> = ref(null)

ref(null) と書いてるのに、型には null が含まれてない

<考え方>

  • ref(null) は「初期値として null を入れる」という意味

  • Ref は「中に number か string しか入らない箱」という意味

▼ランダムにカードを1枚引く関数 drawCard() を作る

このようなボタンを作った。

    <button @click="drawCard">カードを引く</button>

<やりたいこと>

  • ボタンを押下したらdrawCardが動く
  • tarotCardsからカードをランダムに一枚引く(Math.randomを使う)
  • 表か裏かをランダムに決める
  • 引いたカードのid、名前、内容(表か裏のどちらか)を「今日の運勢」の下に表示させる

Math.randomを使うんだろうな、ということはわかったけど、実際の書き方が全然思い浮かばなかった。。😢
GPTにレクチャーをお願いした。

①Math.random() は 0 以上 1 未満の「小数」を返してくれる関数

Math.random() // 0.2857 や 0.9991 や 0.0032 のような数

②これを使ってインデックス番号を作る!
たとえばカードが 22枚あるなら、配列のインデックスは 0 〜 21 。

const index = Math.floor(Math.random() * 22)
  • Math.random() * 22 → 0〜21.999...
  • Math.floor(...) → 小数点以下を切り捨てて、0〜21の整数になる!

tarotCards.length で枚数を自動で取得(22って決め打ちしない)
(今回はタロットだから決められた枚数ではあるけど)

const index = Math.floor(Math.random() * tarotCards.length)
const card = tarotCards[index]

これらを drawCard関数として使うので

// カードを一枚選ぶ関数 drawCard
function drawCard () {
  const index = Math.floor(Math.random() * tarotCards.length)
  const card = tarotCards[index]
  selectedCard.value = card
}

ここでTSエラーが出た。

型 'TarotCard' を型 'string | number | null' に割り当てることはできません。

これは、宣言している selectedCard の型は
const selectedCard: Ref<string | number | null> = ref(null)
↑こうなっているけど、実際に代入してる card は TarotCard 型のオブジェクト

export const tarotCards: TarotCard[] = [
  {
    id: 0,
    name: '愚者(The Fool)',
    normalMeaning: '自由、冒険、無限の可能性',
    reverseMeaning: '無計画、不安定、軽率',
  },

selectedCard の宣言を修正する。

<script setup lang="ts">
import { tarotCards, TarotCard } from '@/data/tarotCards'
import { ref, type Ref } from 'vue' // ref型を使う

// 選ばれたカード の型付け
// const selectedCard: Ref<number | string | null> = ref(null);
const selectedCard: Ref<TarotCard | null> = ref(null)

// カードを一枚選ぶ関数 drawCard
function drawCard() {
  const index = Math.floor(Math.random() * tarotCards.length)
  const card = tarotCards[index]
  selectedCard.value = card
}
</script>

そうすると、またTSエラーが出た。。

'TarotCard' は型であり、'verbatimModuleSyntax' が有効であるときは、型のみのインポートを使用してインポートされる必要があります。

調べたら、TypeScript の「型は型だけとしてインポートすること」 というルールによるもの。

import部分を修正する。

import { tarotCards, type TarotCard } from '@/data/tarotCards'

次は引いたカードの内容を表示させる!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?