はじめに
ども、最近、#週一アプリチャレンジというものをやり始めた人です。
毎週土曜日にアプリを作る配信をする企画です。
今回は、その二回目に作ったビンゴアプリの話をします。
アプリ↓
リポジトリ↓
何を作ったの?
ビンゴアプリです。
1~nまでのランダムな整数を表示してくれるやつです。
デザイン性は皆無ですが、なかなかいいものができたと思ってます。
機能
ここからは、このビンゴアプリが持つ機能を紹介していきます。
数字が高速で切り替わる
ビンゴのメイン画面に飛ぶと、三つのボタンがあると思います。
その一番上のボタンを押すと、ルーレットが開始します。
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.numList
とthis.alreadyList
を使って、まだ出ていない数字のリストの作成を行っています。
上で表示している数字はこの、未出リストから取り出しているので、重複なく数字を取り出すことができています。
選ばれた数字に色がつく
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-for
がv-chip
ではなく、v-col
についているのは、v-row
につけたjustify
がv-chip
に適用されないからです。
(v-for
とv-else
の併用が推奨されていないのも理由の一つ)
v-if="alreadyList.includes(num)"
これで、this.alreadyList
にnum
(numListの中の数字)があるかを確認しています。
もし、含まれていた場合は、color
プロパティが与えられた、青色チップが表示されます。
そうでなかった場合は、v-else
がついている、色なしチップが表示されます。
JWTを使った状態保存
SAVEボタンを押すと、こんなダイアログが表示されると思います。
技術的に、クリップボードに保存する機能をつけれなかったので、自分でコピーするようになっていますが、これを使うことで、状態の保存/復元ができるようになっています。
状態の復元は、最初のページの下のボタン、LOAD
と書かれたボタンを押して飛ばされるページで使用できます。
試しに、このトークンを使ってみてください。
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmaXJzdE51bWJlciI6MSwibGFzdE51bWJlciI6IjMwIiwiYWxyZWFkeUxpc3QiOlsxMyw2LDMwLDExXSwiaWF0IjoxNjQ1ODY3NzkyfQ.qpPZmxuW8fXrFgl2S9b56zbdjpepqOFlJ3L6Ph8kbSg
多分、1-30の6,11,13,30が埋まっているルーレットが読み込まれると思います。
ならなかったら、コメントかDMください
さて、内部構造の説明をしていきましょう。
このサイトを見るとわかると思いますが、JWTを使うことができるnode.jsライブラリは三つあります。(ほかにもあるけど、公式が認めてる(?)ライブラリがこの三つだと思う...)
今回は、その中でも最もスターが多かった
を使うことにしました。
とりあえず、インストールしましょう。
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に関しては、この二つの記事がとてもわかりやすいです。
ぜひ
さいごに
#週一アプリチャレンジという、毎週一個アプリ出す企画始めました。
軽いやつに関しては記事化までいかないと思いますが、
重たいものに関しては、今回みたいに記事にします。
どうぞ、よろしくお願いします。
じゃ、
ノシ