
個人的に新しい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
そんなこんなで実際に出来上がったのがこちら。