0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Vue.jsで作るビンゴアプリ!

Last updated at Posted at 2022-02-26

はじめに

ども、最近、#週一アプリチャレンジというものをやり始めた人です。

毎週土曜日にアプリを作る配信をする企画です。
今回は、その二回目に作ったビンゴアプリの話をします。


アプリ↓

リポジトリ↓

何を作ったの?

ビンゴアプリです。
1~nまでのランダムな整数を表示してくれるやつです。

image.png

デザイン性は皆無ですが、なかなかいいものができたと思ってます。

機能

ここからは、このビンゴアプリが持つ機能を紹介していきます。

数字が高速で切り替わる

ビンゴのメイン画面に飛ぶと、三つのボタンがあると思います。
その一番上のボタンを押すと、ルーレットが開始します。

ここで使ってる変数
this.numList = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] // 1~nまでの数列
this.bingoNumber = 0 // 上に表示してる数字
this.alreadyList = [] // 既出の数字を格納
const loadBingo = setInterval(() => {
  this.bingoNumber = this.numList[Math.floor(Math.random() * this.numList.length)]
}, 100)
setTimeout(() => {
  clearInterval(loadBingo)
  const notYetList = this.numList.filter(i => this.alreadyList.indexOf(i) === -1)
  this.bingoNumber = notYetList[Math.floor(Math.random() * notYetList.length)]
}, 1500)

setInterval()は、一定間隔で何度も処理をする関数です。
これをしたことで、100ミリ秒に一度、1-10までの数列からランダムで数字が選ばれるようになっています。
このsetInterval()は、clearInterval()を使うことで止めることができます。
ここでは、setTimeout()という関数を使って、1500ミリ秒待ってから1-10の中から数字を選ぶ処理を止めています。

下から三行目のnotYetListは、this.numListthis.alreadyListを使って、まだ出ていない数字のリストの作成を行っています。
上で表示している数字はこの、未出リストから取り出しているので、重複なく数字を取り出すことができています。

選ばれた数字に色がつく

image.png
選ばれた数字には色が付きます。

this.numList = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] // 1~nまでの数列
this.alreadyList = [2, 8] // 既出の数字を格納
<v-row class="text-center" justify="center">
  <v-col
    cols="12"
    sm="1"
    v-for="num in numList"
    :key="num"
  >
    <v-chip
      v-if="alreadyList.includes(num)"
      v-text="num"
      color="light-blue lighten-1"
    />
    <v-chip v-else v-text="num" />
  </v-col>
</v-row>

v-colについているv-forで1-10までの数列を回しています。
ちなみに、v-forv-chipではなく、v-colについているのは、v-rowにつけたjustifyv-chipに適用されないからです。
v-forv-elseの併用が推奨されていないのも理由の一つ)

v-if="alreadyList.includes(num)"

これで、this.alreadyListnum(numListの中の数字)があるかを確認しています。
もし、含まれていた場合は、colorプロパティが与えられた、青色チップが表示されます。
そうでなかった場合は、v-elseがついている、色なしチップが表示されます。

JWTを使った状態保存

SAVEボタンを押すと、こんなダイアログが表示されると思います。
image.png
技術的に、クリップボードに保存する機能をつけれなかったので、自分でコピーするようになっていますが、これを使うことで、状態の保存/復元ができるようになっています。

状態の復元は、最初のページの下のボタン、LOADと書かれたボタンを押して飛ばされるページで使用できます。

試しに、このトークンを使ってみてください。

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmaXJzdE51bWJlciI6MSwibGFzdE51bWJlciI6IjMwIiwiYWxyZWFkeUxpc3QiOlsxMyw2LDMwLDExXSwiaWF0IjoxNjQ1ODY3NzkyfQ.qpPZmxuW8fXrFgl2S9b56zbdjpepqOFlJ3L6Ph8kbSg

多分、1-30の6,11,13,30が埋まっているルーレットが読み込まれると思います。
image.png
ならなかったら、コメントかDMください


さて、内部構造の説明をしていきましょう。

このサイトを見るとわかると思いますが、JWTを使うことができるnode.jsライブラリは三つあります。(ほかにもあるけど、公式が認めてる(?)ライブラリがこの三つだと思う...)
今回は、その中でも最もスターが多かった

を使うことにしました。

とりあえず、インストールしましょう。

console
npm install jsonwebtoken

使い方を紹介します。
といっても、公式のREADMEに書いてあることの復唱になりますが((

const jwt = require('jsonwebtoken');
const token = jwt.sign({ foo: 'bar' }, 'shhhhh')

この、'shhhhh'というやつは、JWTのシークレットと呼ばれるやつで、これをもとにJWTのエンコード/デコードが行われます。
これが漏れると、セキュリティ上相当危ないそうなので、.envで保存するなど、注意しましょう

さて、このコードでエンコードができます。
{ foo: 'bar' }という部分は、JWTから取ることができる内容の部分です。
ここには、基本、なんでも入れていい...はず((

公式の資料では、ここに、ユーザー名やアドミンかどうかのt/fが格納されてました。
僕のビンゴアプリでは、最初の数と最後の数、あと、既出リストを格納しています。


次にデコードの話ですが、これも超簡単で、

const decoded = jwt.verify(token, 'shhhhh');
console.log(decoded.foo) // bar

たったのこれだけ!

まとめると、

const jwt = require('jsonwebtoken');
const token = jwt.sign({ foo: 'bar' }, 'shhhhh')

const decoded = jwt.verify(token, 'shhhhh');
console.log(decoded.foo) // bar

たったの四行だけで、エンコード/デコードの実装ができてしまいます!
すごいですね。
最初見たときは驚きました。

ちなみに、

上のロード機能でデコードした情報はどうやって移行しているのかというと、vuexを使っています。

Vuexに関しては、この二つの記事がとてもわかりやすいです。
ぜひ

さいごに

#週一アプリチャレンジという、毎週一個アプリ出す企画始めました。

軽いやつに関しては記事化までいかないと思いますが、
重たいものに関しては、今回みたいに記事にします。

どうぞ、よろしくお願いします。

じゃ、
ノシ

0
2
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
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?