完成形
準備
vue cliを使う。
https://cli.vuejs.org/
ここでつまづいたら、インストール方法に関する記事はこの辺
https://qiita.com/kamitomo/items/34451b11caaf51bd2498
$ vue --version
3.10.0
(コマンド実行する所と結果を見分けるため、コマンド実行している所は先頭に$
を付ける)
準備は以上。
vueに必要なファイルを自動生成してもらう
$ vue create ui
uiはフォルダ名。好きに書き換えて良い。
下記のように質問来るけど、defaultでenterを押す
Vue CLI v3.10.0
? Please pick a preset: (Use arrow keys)
❯ default (babel, eslint)
Manually select features
これでvueに必要なファイルの作成は完了。
下記のようなコマンド実行すると、localhostでサーバーが起動する。
$ cd ui
$ yarn serve
$ yarn serve
DONE Compiled successfully in 4303ms 9:59:38 AM
App running at:
- Local: http://localhost:8082/
Note that the development build is not optimized.
To create a production build, run yarn build.
ポート番号は空いている所が自動的に。
(ちなみに、vue cli 3.10.0からは、--port
がサポートされたようで)
ブラウザで見ると、こんな感じに
トップページを書き換える
トップページはsrc/App.vueというファイルになる。
書き換え前はこんな感じ
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png">
<HelloWorld msg="Welcome to Your Vue.js App"/>
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
name: 'app',
components: {
HelloWorld
}
}
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
書き換え後
<template>
<div id="app">
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'app',
}
</script>
<style>
</style>
1行<router-view></router-view>
を追加したので注意。
ここにページが自動的に埋まるようになる。
それ以外の所は装飾して遊んでみてください。
vue routerを使ってみる
これを使うと複数のページをURLに従って切り替えしてくれる。
先ほどの<router-view></router-view>
が切り替わる。
今回の範囲は1ページなので使わなくていいけど、拡張できるように使ってみる。
先程作成したuiフォルダで
$ yarn add vue-router
これで、vue routerが使えるようになったので、vue routerを使うjsファイルを作成する。
ファイル名は何でも良い。
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router);
function loadView(view) {
return () => import(`@/views/${view}.vue`)
}
const router = new Router({
mode: 'history',
routes: [
{
path: "/",
name: "check",
component: loadView('Check'),
},
]
})
export default router
ブラウザで/
のパスの場合に表示するページがCheck.vueになるという設定で。
だいたいこんな感じで動く。
router.jsを使う設定
main.jsが本当に中心となるファイルで、ここに書くと実行してもらえるようにできている。
App.vueもここから呼び出されている。
ここでrouter
を読み込んで、vueに使ってもらうように設定する。
router.jsを読み込むコードはimport router from './router'
import Vue from 'vue'
import App from './App.vue'
import router from './router'
Vue.config.productionTip = false
new Vue({
router,
render: h => h(App),
}).$mount('#app')
./routerのように.js
は省略(書いてもいいけど)
importで'vue'
みたいに先頭に./
書いていないやつはライブラリ。
ライブラリは先ほどのようにyarn add
みたいな感じでもらってくる。
importで@/
って書いてあったらはsrc/
の事。今回は入ってない。
という知識を持っていたら色々なサンプルコードが読めるようになる。
Check.vueの作成
src/views/Check.vueというファイルを作成する
<template>
<div>check</div>
</template>
<script>
export default {
name: "Check"
}
</script>
<style scoped>
</style>
これは、先程のrouter.js
から呼び出すファイルとなる。
ここまでの実装が完了すると、ブラウザで開いた場合は、こんな感じ
あとは、ここの実装を増やしていくだけで終わり。
v-if, data, methodsを使ってみる
計算中か計算中以外の表示を切り替える。
ボタンを押したら切り替わるようになる。
<template>
<div>
<div v-if="isChecking">
<button @click="checkAns">こたえあわせ</button>
</div>
<div v-else>
<button @click="start">スタート</button>
</div>
</div>
</template>
<script>
export default {
name: "Check",
data: () => ({
isChecking: false,
}),
methods: {
checkAns() {
this.isChecking = false
},
start() {
this.isChecking = true
}
},
}
</script>
<style scoped>
button {
font-size: 24px;
}
input {
font-size: 24px;
width: 60px;
}
div {
font-size: 24px;
}
</style>
画面切り替えはこれで完成。
あとはロジックを増やしていくだけ。
styleは好みで設定。
タグの中に<div style="font-size: 24px">
でもよい。
{{{xxxx}}}とv-modelを使ってみる
- 計算できるように、ランダムの数字を表示する
- 入力できるようにする
...変更なし
<div v-if="isChecking">
<br>
{{leftNum}} + {{rightNum}} =
<input type="number" v-model="ans" style="font-size: 24px; width: 60px">
<br>
<button @click="checkAns" style="font-size: 24px">こたえあわせ</button>
</div>
...変更なし
<script>
export default {
name: "Check",
data: () => ({
leftNum: 0,
rightNum: 0,
ans: "",
isChecking: false,
}),
methods: {
checkAns() {
this.isChecking = false
},
next() {
const l = Math.floor(Math.random() * 9) + 1
const r = Math.floor(Math.random() * 9) + 1
this.leftNum = l
this.rightNum = r
this.ans = ""
},
start() {
this.isChecking = true
this.next()
}
},
}
</script>
- {{{変数名}}}で、dataの値が表示できる
- v-model="変数名"で、inputのデータをセットすることができる
ほぼ出来上がった感がある。
watchを使ってみる
- 計算にかかった時間を計測する。
- isCheckingがtrue中の時間を計測すればよい
- 単にwatchを使いたいだけで、実際は使わなくてもいいけど・・・
<div v-else>
<br>
<button @click="start" style="font-size: 24px">スタート</button>
<br>
<div>
じかん:{{elapsedTime}}びょう
</div>
</div>
...
data: () => ({
leftNum: 0,
rightNum: 0,
ans: "",
isChecking: false,
startTime: 0,
elapsedTime: 0,
}),
methods:{
....
},
watch: {
isChecking(v) { // isCheckingが変更されるたびに呼ばれる
if (v) { // isCheckingがtrueに変更
this.startTime = Date.now()
} else { // isCheckingがfalseに変更
this.elapsedTime = Math.floor((Date.now() - this.startTime) / 1000)
}
}
},
UXを向上させる
このままだと入力が難しい!!!
- スマホブラウザで電卓キーボードに切り替える
- オートフォーカス(Vue.nextTickを使ってみる)
電卓キーボードに
スマホでみた時に、入力しやすさを考えて電卓キーボードに変更したい
<input type="number" v-model="ans" pattern="\d*" id="ans">
オートフォーカス(Vue.nextTickを使ってみる)
- こたえあわせを押す毎にキーボードが閉じられるので、入力枠にオートフォーカスする必要がある
- オートフォーカスは画面の描写が終わった後にしかできない難しさがあるので、技を使う必要がある
...
<script>
import Vue from 'vue'
next() {
const l = Math.floor(Math.random() * 9) + 1
const r = Math.floor(Math.random() * 9) + 1
this.leftNum = l
this.rightNum = r
this.ans = ""
Vue.nextTick(function () {
document.getElementById('ans').focus();
})
},
この書き方なら応用がきくと思うので、ここではこんな感じで書いてみた。
リリース用のファイルを作成する
$ yarn build
これでdistフォルダが自動的に作成され、その中のファイルが公開用のファイル
Webサービスとして全世界に公開
Firebase Hostingの設定
- firebaseのhostingを使うと先程作ったSPAを簡単に公開できる
- https://firebase.google.com/?hl=ja
- firebaseにアクセスして
プロジェクトを追加
をクリック
プロジェクト名は好きな名前で(ここで付けた名前がURLになる)
「今は必要ない」を選択して「プロジェクトを作成」をクリックする。
A/Bテスト・・・とかなんとか色々できそうな雰囲気が伝わってくるが、webサービスでは使えないものが並んでいる。
表示される順番でコマンドを実行する。
注意点があるとすると、firebase login
でログイン済み
みたいな感じになったら、firebase logout
を実行して、再度実行すると、後に問題が出ない。
一番最初に作ったuiフォルダ内でfirebase initを実行する
上下キーでHostingを選択して、スペースキーで選択して、enter
$ cd ui
$ firebase init
....
◯ Database: Deploy Firebase Realtime Database Rules
◯ Firestore: Deploy rules and create indexes for Firestore
◯ Functions: Configure and deploy Cloud Functions
❯◯ Hosting: Configure and deploy Firebase Hosting sites
◯ Storage: Deploy Cloud Storage security rules
先程作成したプロジェクト名を選択してenter
? Select a default Firebase project for this directory:
[don't setup a default project]
❯ test97668183 (test97668183)
[create a new project]
先程yarn build
作成したdist
と入力してenterすると、distフォルダがアップロードできる
? What do you want to use as your public directory? (public) dist
親切に、シングルページアプリケーションか?
と聞いてくるのでyを入力
? Configure as a single-page app (rewrite all urls to /index.html)? (y/N) y
index.htmlがあるけど上書きするか?と聞いてくるので、N
? File dist/index.html already exists. Overwrite? (y/N)
distフォルダをサーバー(firebase hosting)にアップロード
$ firebase deploy
完成。
URLはfirebaseapp.comだけではない
デプロイ後にURLはfirebaseapp.comのほうを案内されるけど、web.appでもアクセスできる。
https://edu-keisan.firebaseapp.com/
https://edu-keisan.web.app/
アクセス先は同じ。
補足:xxxx.mapは削除してみたい
yarn build の時に使われる設定例としてやってみる。
module.exports = {
productionSourceMap: false,
}
このファイルを作成して、yarn build
すると、mapファイルが作成されていない。
あとは、これをfirebase deploy
とするとアップロードされる。
補足:ルート以外のパスで動かしたい
URLのパスでルート以外で動作させたいという気になった場合は、publicPathを設定する。
module.exports = {
publicPath: 'calc',
productionSourceMap: false,
}
とかとか、あとは好きに検索して遊んでみて。
最後に
せいかい、まちがいカウントに関しては、ここまで来ると自力で作れると思うので、あとは自力でやってみてください。
ここにあるコードでは出てきません。