個人的に新しいJavascriptフレームワークを素振りする際の定番がクリッカー(某クッキーのアレ)だったりする。今回はごくごく簡素なクリッカーを作りつつVue.jsの使い方を紹介したいと思う。
ひな型の作成
ペライチ想定なのでvue-routerなし、テストとかも今回はなしで。
$ vue init webpack vue-clicker ? Project name vue-clicker ? Project description simple clicker ? Author ***** ? Vue build standalone ? Install vue-router? No ? Use ESLint to lint your code? Yes ? Pick an ESLint preset Standard ? Setup unit tests with Karma + Mocha? No ? Setup e2e tests with Nightwatch? No vue-cli · Generated "vue-clicker". To get started: cd vue-clicker npm install npm run dev Documentation can be found at https://vuejs-templates.github.io/webpack
また、必要なパッケージをインストールしておく。
$ cd vue-clicker $ yarn yarn yarn install v1.2.1 info No lockfile found. [1/5] 🔍 Validating package.json... [2/5] 🔍 Resolving packages... [3/5] 🚚 Fetching packages... [4/5] 🔗 Linking dependencies... [5/5] 📃 Building fresh packages... success Saved lockfile. warning Your current version of Yarn is out of date. The latest version is "1.3.2" while you're on "1.2.1". info To upgrade, run the following command: $ curl -o- -L https://yarnpkg.com/install.sh | bash ✨ Done in 126.18s.
画面設計
クリッカーとしての最低要件を考えると
- カウンター
- カウントアップするためのボタン
- 一定のカウントになるとアンロックされるレベルアップ機能
なんかが必要となるだろう。
大まかな画面構成が決まったら、それをパーツごとに分解してひとまず見た目だけのモックを作成していく。
- カウンター: 'src/components/Counter.vue'
<template> <p class="count">12345</p> </template> <script> export default { name: 'counter' } </script> <style scoped> .count { font-size: xx-large; } </style>
- カウントアップボタン:
src/components/CountupButton.vue
<template> <button>+1</button> </template> <script> export default { name: 'countup-button' } </script> <style scoped> button { font-size: x-large; } </style>
* ランクアップメニュー: 'src/components/RankupMenu.vue'
<template> <div class="menu"> <p>ほげほげ</p> <button>0 (3/10)</button> </div> </template> <script> export default { name: 'rankup-menu' } </script> <style scoped> .menu { border: 1px dotted black; font-size: large; } </style>
また、作成したコンポーネントを本体たるsrc/App.vue
で読み込んで並べていく。今回使用したwebpackの設定ではimportの際に*.vue
や*.js
の拡張子は省略できる。
<template> <div id="app"> <div id="main"> <counter></counter> <countup-button></countup-button> </div> <div id="side"> <rankup-menu></rankup-menu> <rankup-menu></rankup-menu> <rankup-menu></rankup-menu> <rankup-menu></rankup-menu> </div> </div> </template> <script> import Counter from './components/Counter' import CountupButton from './components/CountupButton' import RankupMenu from './components/RankupMenu' export default { name: 'app', components: { Counter, CountupButton, RankupMenu } } </script> <style> div#app { width: 100%; display: -webkit-inline-flex; display: inline-flex; -webkit-flex-direction: row; flex-direction: row; } div#main { width: 70%; border: 1px solid blue; display: -webkit-inline-flex; display: inline-flex; -webkit-flex-direction: column; flex-direction: column; } div#side { width: 30%; border: 1px solid red; display: -webkit-inline-flex; display: inline-flex; -webkit-flex-direction: column; flex-direction: column; } </style>
ここまでで一旦yarn dev
なんかで起動して見た目を確認、調整を行う。
ひとまず画面構成まで · blue1st/vue-clicker@ae57923 · GitHub
機能の実装
さっそくハリボテに実際の機能を与えていく。
親要素から子要素への変数の受け渡し
https://jp.vuejs.org/v2/guide/components.html#プロパティ検証
まずは何と言ってもカウントを管理する必要がある。これはアプリケーション全体で共通して使用されるデータなので、App.vue
に変数count
として定義する。
data () { return { count: 0 } }
この値をCounterコンポーネントに渡す。これはHTMLタグに:val="VALUE"
のような形で与えれば良い。
<counter :count="count"></counter>
また、受け渡される側であるcomponents/Counter.vue
はそれをprops
として受け取る。
props: { count: Number }
そして、それをテンプレートで表示する。
<p class="count">{{count}}</p>
propsによるデータの受け渡し · blue1st/vue-clicker@6ffc0af · GitHub
子要素から親要素へのアクションの受け渡し
クリッカーなので、ボタンを押すことでカウンターの数値を増やしたい。今回のコードで言い換えればcomponents/CountupButton.vue
のクリックイベントをトリガーとしてApp.vue
のcount
を増減させるということである。
ひとまず子要素であるcomponents/CountupButton.vue
にイベント発行を行う仕組みを作ってみる。
タグに@event="Method"
と記述することで記述したイベントが生じた際に実行するメソッドを定義できる。
<button @click="countup(1)">+1</button>
また、ここで叩かるメソッドをmethods
項で定義できる。この中で$emit
を用いてこの要素自体がadd
というイベントを発火するものとしてみる。
methods: { countup (num) { this.$emit('add', num) } }
https://jp.vuejs.org/v2/api/#vm-emit
発行されたadd
イベントをApp.vue
で受け取り、カウントアップするようにしてみる。
<countup-button @add="addCount"></countup-button>
methods: { addCount () { this.count += 1 } }
https://jp.vuejs.org/v2/api/#v-on
このようにして子要素が間接的に親要素の変数をいじることができる。
emit/onでカウントアップを実装 · blue1st/vue-clicker@ba46c42 · GitHub
ランクアップメニューを作る
ランクアップメニューはほぼ同じものが沢山作る必要がある。このあたりはmixinsやextendsを用いることで効率的に作成できる。
https://jp.vuejs.org/v2/api/#mixins
流石に面倒になってきたので詳細は省く。
add RankupMenu · blue1st/vue-clicker@e5b2d27 · GitHub
ビルド&Github Pagesとしてデプロイ
そんなこんなで満足いくものができたらビルドする。
まず作業用のブランチを作成。
$ git checkout -b release
ビルドの前に、プロジェクトのGithub Pagesのはhttps://{ACCOUNT}.github.io/{PROJECT}/
というURLになるため、それ用にビルドの設定を修正しておく。
config/index.js
のassetsPublicPath
項を今回は/
から/vue-clicker/
に変更。
そんなこんなでビルド。
yarn build yarn run v1.2.1 $ node build/build.js Hash: 9d6fed5d68fbd8909140 Version: webpack 3.8.1 Time: 7031ms Asset Size Chunks Chunk Names static/js/app.f23ef1ad0fab924dbf86.js 3.45 kB 0 [emitted] app static/js/vendor.74aab6a9f9d88781cc24.js 94.8 kB 1 [emitted] vendor static/js/manifest.63dbf12684c82d83fc78.js 1.49 kB 2 [emitted] manifest static/css/app.be925e3357c3d239f2b1180af9f3dd63.css 619 bytes 0 [emitted] app static/js/app.f23ef1ad0fab924dbf86.js.map 36 kB 0 [emitted] app static/js/vendor.74aab6a9f9d88781cc24.js.map 791 kB 1 [emitted] vendor static/js/manifest.63dbf12684c82d83fc78.js.map 14.2 kB 2 [emitted] manifest index.html 448 bytes [emitted] Build complete. Tip: built files are meant to be served over an HTTP server. Opening index.html over file:// won't work. ✨ Done in 11.18s.
出来上がったdist
はgitignoreで無視されてしまうのでforceオプション付きのadd/commit。
$ git add --force dist/ $ git commit [release 4ebe68e] release file 8 files changed, 16 insertions(+) create mode 100644 dist/index.html create mode 100644 dist/static/css/app.be925e3357c3d239f2b1180af9f3dd63.css create mode 100644 dist/static/js/app.f23ef1ad0fab924dbf86.js create mode 100644 dist/static/js/app.f23ef1ad0fab924dbf86.js.map create mode 100644 dist/static/js/manifest.63dbf12684c82d83fc78.js create mode 100644 dist/static/js/manifest.63dbf12684c82d83fc78.js.map create mode 100644 dist/static/js/vendor.74aab6a9f9d88781cc24.js create mode 100644 dist/static/js/vendor.74aab6a9f9d88781cc24.js.map
dist以下を指定してgh-pages
というブランチとしてプッシュするとGithub Pagesとして公開できる。
git subtree push --prefix dist/ origin gh-pages
そんなこんなで実際に出来上がったのがこちら。