【Vue.js】Composition-APIで簡単なタイピングゲームを作ってみました

[以前Vue.jsで作った奴](https://qiita.com/higa08/items/60ee051f5848440d8e6d)をComposition-APIに書き換えて＋αしてみました。

ロジックとかは大体同じです。

# 環境
|  | version |  
|---|---|
|macOS Catalina  |10.15.7  |
|npm  |6.9.0  |
|node |10.16.0  |
|vue  |2.6.11 |
|@vue/composition-api  |1.0.0-rc.2 |

# 完成品
![demo](https://gyazo.com/acef9cedb1cbdd20b14836432156139f/raw)

![demo](https://gyazo.com/2a0a56e8c89fd5cbdc54a3997384e88a/raw)

```vue:AppVue
<template>
  <div id="app">
    <div v-if="!playing">Enterキーでスタート</div>
    <div v-else>
      <div>残り{{ time }}秒</div>
      <div>単語数：{{ typedWord }} / ミス：{{ miss.num }}</div>
      <br />
      <div>
        <div v-if="miss.status">😫</div>
        <div v-else><br /></div>
        <span style="opacity: 0.3;">{{ typeChar }}</span>
        <span>{{ nowWord }}</span>
      </div>
    </div>
    <br />
    <div v-if="!time">ゲーム終了！おつかれさまでした！🍻</div>
  </div>
</template>

<script>
import { ref, reactive, toRefs } from '@vue/composition-api';
export default {
  setup() {
    // 単語関係ーーーーーーーーーーーーーーーーーーーーーーー
    const wordStore = reactive({
      nowWord: '',  // 出題されている単語
      typeChar: '', // 入力した単語の一文字
      typedWord: 0, // 入力し終えた単語の数
      words: [      // 出題単語
        'dog',
        'cat',
        'monkey',
        'elephant',
        'giraffe',
        'penguin',
        'lion',
        'tiger',
        'pig',
        'cow',
      ],
    });
    // wordsからランダムな単語を1つ取り出す
    const setWord = () => {
      wordStore.nowWord = wordStore.words[Math.floor(Math.random() * wordStore.words.length)];
    };

    // タイピング関係ーーーーーーーーーーーーーーーーーーーー
    const miss = reactive({
      // ミスの回数とミスしたかどうか
      num: 0,
      status: false,
    });
    const keydown = (e) => {
      // 間違えたときの処理
      if (wordStore.nowWord[0] !== e.key) {
        miss.num++;
        miss.status = true;
        return;
      }
      miss.status = false;
      // typeCharに入力できた文字を追加していく
      wordStore.typeChar += e.key;
      // 入力できたらnowWordの頭文字を削除していく
      wordStore.nowWord = wordStore.nowWord.slice(1);
      // 単語を入力し終えたときの処理
      if (!wordStore.nowWord) {
        wordStore.typedWord++;
        wordStore.typeChar = '';
        setWord();
      }
    };

    // カウントダウン関係ーーーーーーーーーーーーーーーーーー
    const time = ref(10); // カウントダウンのタイム
    const countDownTimer = () => {
      const id = setInterval(() => {
        time.value--;
        if (!time.value) {
          // ゲーム終了。keydown関数のキーイベントを削除
          removeEventListener('keydown', keydown);
          clearInterval(id);
        }
      }, 1000);
    };

    // ゲーム開始ーーーーーーーーーーーーーーーーーーーーーー
    const playing = ref(false); // ゲームが始まっているかどうか
    const startGame = (e) => {
      // 入力がEnterキーでなければゲームが始まらない
      if (e.key !== 'Enter') return;
      playing.value = true;
      // 各関数実行
      // startGame関数のキーイベントを削除
      removeEventListener('keydown', startGame);
      // keydown関数のキーイベントを発火
      addEventListener('keydown', keydown);
      setWord();
      countDownTimer();
    };
    // startGame関数のキーイベント発火
    addEventListener('keydown', startGame);

    return {
      ...toRefs(wordStore),
      playing,
      miss,
      time,
      setWord,
    };
  },
};
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  font-size: 20px;
  margin-top: 100px;
}
</style>
```

***
***

ロジックとそれに関連する変数ごとに分けてまとめるように意識しました。

素のjavascriptで書いてる感じが強かったです。

もっとCompotision-APIの要素を入れたかったですが、これが限界でした笑