サーバレス構成のWebアプリ開発を担当し、そこでVue.jsを使ってみたので採用した経緯と、Vue.jsの何を使ったかを紹介する。
これまでのWebアプリ開発
JavaのWebアプリ開発ならThymeleafやFreemarkerなどのテンプレートエンジンを使用していた。
サーバレスだと、HTMLとJavaScriptで表示の処理を行うため、JavaScriptの処理が増える。
よく使われるのはjQueryによってDOMを操作し、HTMLを動的に変更する方法だろう。
jQueryのDOM操作は辛いよ
jQueryを使ったことがあればお分かりだと思うが、jQueryによるDOM操作は「このイベントで、このvalueがxxxなら、このDOMを変更する」という手続き型のコードになる。
JavaScriptの処理が増えると、この手続き型のコードが増えてデータと状態の管理が煩雑になる。
また、JavaScript側に表示の処理があるためHTMLを簡単に変更できない。
そこでVue.jsですよ
SPAっぽい要件なので、SPAに適したJavaScriptフレームワークを使う方がよさそう。
SPAがやりたいわけではないが。
Vue.jsは社内で検証の候補になっていたので採用してみた。
公式ガイドをさらっと読むと、HTMLに値を埋め込める、条件分岐、ループを組み込めるので、テンプレートエンジンと同じことができそう。
クライアントの開発は一任されていたので、試しやすかったのもある。
Vue.jsのはじめかた
お手軽にはじめるなら script
タグに1行追加するだけ。
<!-- 開発バージョン(警告出力とデバッグモードあり) -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<!-- 本番バージョン(警告出力なし、圧縮済み -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16"></script>
但し、webpackでビルドが必要な機能は使えない。例えば単一ファイルコンポーネント。
単一ファイルコンポーネントはHTMLを構成するヘッダ、ボディなどを部品ごとに分けて扱える。
便利ではあるが、Node.jsのツール(npm, webpack, vue-cli)が必要になる。
公式ガイドでは、最初は script
から使用することをおすすめしている。
機能数も少ないので script
から使用する。
Vueのアプリ開発
Vueインスタンスの作成
画面ごとにHTMLを分けたので、HTMLごとにルートVueインスタンスを生成。
Vueインスタンスで使用するオプションは el
, data
, methods
, computed
のみ。
var vm = new Vue({
el: '#app',
data: {
items: [
{
isbn: '4873118069',
title: 'サーバーレスシングルページアプリケーション',
publisher: 'オライリージャパン',
price: 2808
},
{
isbn: '4798155160',
title: 'AWSによるサーバーレスアーキテクチャ',
publisher: '翔泳社',
price: 3888
}
]
},
methods: {
// メソッド
},
computed: {
// 算出プロパティ
}
})
- el
- Vueインスタンスの対象となるHTML要素を指定する。
- data
- バインドする変数を格納する。変数の値が変更されるとHTMLに反映される。
- methods
-
v-on
で呼び出す関数を記述する。 - computed
- 算出プロパティ。依存するものが更新されなければ以前計算された結果を返す。
HTMLにJavaScriptの値を埋め込む
Vueインスタンスの data
の変数を {{変数}}
のように2重の中括弧で囲むとHTMLに値が埋め込める。
変数を処理させて表示する場合は算出プロパティを使用する。
例えば、合計金額を算出して表示するには以下のように記述する。
var vm = new Vue({
el: '#app',
data: {
items: [
{
isbn: '4873118069',
title: 'サーバーレスシングルページアプリケーション',
publisher: 'オライリージャパン',
price: 2808
},
{
isbn: '4798155160',
title: 'AWSによるサーバーレスアーキテクチャ',
publisher: '翔泳社',
price: 3888
}
]
},
methods: {
// メソッド
},
computed: {
priceTotal: function() {
var total = 0;
for (var item in items) {
total += item.price;
}
return priceTotal;
}
}
})
合計金額:{{priceTotal}}
ディレクティブの使い方
Vue.jsはHTMLタグの中にディレクティブという特別な属性を埋め込むことでHTMLを制御する。
使用したディレクティブは以下の通り。
v-if
条件で表示を切り替えるのに使用する。
v-show
も同じ用途で使用されますが、v-show
はCSSの display: none
で表示を隠すのと同じでDOMは消えない。
DOMの追加、削除がない分、描画は v-show
の方が早い。
例えばログインユーザの権限で表示項目を変える場合はDOMに出したくないから v-if
の方がよさそう。
プルダウンやラジオボタンで項目を切り替えるのであれば、v-show
の方がよさそう。
v-for
data
の配列データを1件ずつループで処理するのに使用する。
例えばAjaxでDBから取得したデータを一覧表示する場合に使用される。
一覧を10件ずつ表示する場合は算出プロパティを使用するとよさそう。
var vm = new Vue({
el: '#app',
data: {
items: [], // AjaxでDBから取得
pagination: {
page: 0,
pageSize: 10,
},
startPage: 0,
pageSize: 10,
},
methods: {
// メソッド
},
computed: {
pageItems: function () {
var startPage = this.pagination.page * this.pagination.pageSize;
return this.items.slice(startPage, startPage + this.pagination.pageSize);
},
}
})
<table>
<thead>
<tr>
<th>ISBN</th>
<th>タイトル</th>
<th>出版社</th>
<th>値段</th>
</tr>
</thead>
<tbody>
<tr v-for="item in pageItems">
<td>{{item.isbn}}</td>
<td>{{item.title}}</td>
<td>{{item.publisher}}</td>
<td>{{item.price}}</td>
</tr>
</tbody>
</table>
v-bind
タグの属性に値を埋め込むのに使用する。
例えば class
の属性を動的に切り替えるには <div v-bind:class="disabled: isDisabled"></div>
のように記述すると data
の isDisabled
がtrueの場合に disabled
が埋め込まれる。
v-bind:class
は :class
のように省略して記述することもできる。
また、v-for
と組み合わせて動的にセレクトボックスを作ることができる。
<select>
<option v-for="item in items" :value="item.isbn">{{item.title}}</option>
</select>
v-on
イベントで methods
に記述した関数を呼び出すのに使用する。
例えばボタンクリック時のイベントは v-on:click="ファンクション名"
のように記述する。
また、@click="ファンクション名"
のように省略して記述することもできる。
v-model
input
, select
, textarea
の値を data
の変数にバインドするのに使用する。
v-cloak
v-cloak
を使うことで、値が埋め込まれるまで {{変数}}
がそのまま表示されるのを防ぐことができる。
CSSで display: none
を適用しておきます。
[v-cloak] {
display: none;
}
まとめ
サーバレス構成だとJavaScriptフレームワークは必須かなと思う。
ReactやAngularは分からないが、Vue.jsは使いやすい。
何よりDOM操作から開放されることがよい。