Google Apps Scriptではウェブアプリケーションを作成できますが、そのままでは何の作成支援もありません。最近は、JavaScriptの各種フレームワークでウェブアプリケーションを作成するのが当たり前になってきていて、GAS上でjQueryで頑張るというのは賢明ではありません。そこで今回利用するのが、Vue.js

GUIフレームワークではなくバックエンドの様々な操作を行う為のユーザインターフェースフレームワークで、GUIについては別途Vuetifyと呼ばれるフレームワークが存在する。

※今回はディレクティブと呼ばれる超基本部分だけ。

難易度:


今回使用するサンプルファイル

Vue.jsとは

概要

Vue.jsとは、React.jsAnqularJSなどのようなフレームワークの1つで、軽量且つ高機能、おまけに学習コストが低くて済むと言われるもので、JavaScriptの学習でのある段階まで到達したら、手を出す必要のあるジャンル。それまでのシンプルなJavaScriptでは面倒なDOM操作などを手軽にし、且つ開発を容易にしてくれる裏方です。

Google Apps Scriptでもウェブプリケーション構築で利用する事が可能であり、また全体像があやふやな学習初期であっても、必要な部分にだけ取り入れて使うことも可能(要素の部品化が可能なので、ボタン要素だけまずは学習してみるとか)。

GASで使うメリット

Vue.jsは、シングルページアプリケーション作成が可能という謳い文句で、Google Apps Scriptのような複数のHTMLを駆使する事が難しいものにはもってこいの機能が満載。また、GASで開発をする人達は基本、VBAの開発者などと同様にライトユーザが多いこともあり、学習コストがガッツリ掛かるような他のフレームワークよりも、学習コストが低いメリットが強いです。

基本、CDNのJSファイルをロードすれば良いので、GASのようにあまり柔軟にJSやライブラリを配置できないような開発環境であっても利用が容易なのも利点の1つ。

また、他のフレームワークと違い、学習コストが低いという事は、そのフレームワーク前提でコードを組んでも共有しやすい(後任の人間がスキルに不足があっても、追いつける)。jQueryのように圧倒的に一般的に利用されているものに近いのは良いメリットです(追加でAngularJS学べと言われると絶望するかもしれませんし)

基本スタイル

最も基本となるビューというものを作り、既存のelementにある文字を置き換えるといったケースでは以下のようなコードになる。

  • キノコを料理のボタンには、cookpadという関数を呼び出すように@clickがつけられている(本来はv-onを使う)
  • idがappのビューをロード時にそのまま初期化。{{cookman}}をキノコを調理するよというメッセージをまずセットしてる(dataというセクション)。本来はv-textを使う。
  • 続いて、methodsにて関数を定義。cookpadという関数を用意して、Vueをセットしたvm変数cookmanに値をセットすると、自動的にcookmanのメッセージが連動して入れ替わる(ここがポイント)
  • 予め変更が予定されてる要素とJavaScript、関連メソッドを一塊にしておく(構造化)のが、Vue.jsの特徴。直接DOMを操作するjQueryのような煩雑さが無い。

実行結果

上記のコードを実行してみる。すると、ボタンと初期メッセージが表示され、ボタンをクリックするとメッセージが入れ替わる。

図:jQueryでも出来るけれど、それをより構造化して行えるのがVue.js

Vue.jsでの実装例

ループでデータを生成

スプレッドシートのデータをHTML側で受け取り、ループでデータを生成する。非常によく使うパターンです。これまでの場合、コードを挿入する場所の要素を取得し、ForループでHTMLデータを生成し、要素にinnerHTMLで挿入する。そういったルーチンでした。Vue.jsを用いた場合、予めHTML内で定義してあるので、変数に値を入れただけで、これが完成します。

GAS側コード

  • 取得したスプレッドシートをそのままJSON.stringifyして返すだけでは駄目
  • JSON形式を組み立てて返してあげる際に、1行目のタイトル行をkeyとして利用する(これをHTML側で利用)

HTML側コード

  • 今回テーブルデザインCSSは、こちらのサイトの情報を利用いたしました。
  • Vue.jsの変数spreadの初期値は空にしてあるので、表示しただけではテーブル表示されません。
  • sheetman関数@clickで呼び出すと、GAS側からJSONデータを取得し、vm.spreadに値を格納します。
  • 変数spreadに値が格納されると、<tr v-for=”rec in spread”>以下にデータがループで格納されます。それぞれのTDタグに指定のJSONの値を入れ込むようになっています。
  • v-forがループになりますが、for eachだと思えば良いです。
  • JavaScriptでループの構文やinnerHTMLといったコードは記述の必要がありません。
  • jQueryだと配列にデータを入れて、HTMLにも追加して・・・削除の時は逆を。vue.jsはデータを操作すれば、要素が変わるので、処理を落とすようなことも防げます。
  • computedにて、spread変数の中の件数を自動的に取得し反映しています。

実行結果

入力データの反映と取得

テキストボックスにユーザが入れた情報を取得し、HTML上に即反映。また、その値を取得して次の処理を行う。これも非常によく利用するパターンですね。テキストボックスとHTMLの指定部分とを連結するテクニックです。また、取得したデータでスプレッドシートのデータを検索し、返します。

GAS側コード

  • 単純にシートのデータを取得、配列から合致するレコードがあったら、人口列の値を返します。

HTML側コード

  • this.spreadでテキストボックスの値を取得させています。
  • また、取得時にはv-modelにてデータの表示先を指定してるので、何もせずとも入力後に値がHTMLへ反映します。
  • sheetchk関数にてGAS側検索。結果をalertで単純に表示しています。

実行結果

タグの属性に連結させる

HTMLのタグには例えば、aタグの場合、href属性などがあります。素のJavaScriptだと、document.getElementById(id).hrefといった具合に指定するアレです。この属性値に対してデータを連結する事が可能です。

GAS側コード

  • 単純にスプレッドシートのデータの一部の列だけを取得して二次元配列で返しています。

HTML側コード

  • GAS側からの二次元配列データをv-forにて順番にロードさせています。
  • v-bindは省略記述可能。けれど、aタグの場合わかりにくくなるので、あえてつけています。
  • listは1レコード分入っているので、配列の指定で値を取り出してます。
  • GAS側からのデータの取得がもたつくので、表示は工夫が必要(v-ifやv-cloakを使うと良いかも)

実行結果

インライン画面遷移を実現する

Vue.jsにはcompnentといったものは、routerといったシングルページアプリケーションに役立つ機能があるのですが、Vue.jsをGoogle Apps Scriptで利用する場合に有効なのは、「v-html」です。このv-htmlは使い方を間違えるとXSS問題を引き起こす事があるので、安全なソースや環境下でだけ使うようにと、公式サイトにも記述されています。

componentの場合、templateにて参照できるのは自身のVueのスコープの範囲内であるのと、templateにスクリプトレットでHTMLを突っ込んでも、表示はなされません。そこで利用するのが、v-htmlですが、こちらは外部からのHTMLを取得し流し込めるので、GASで使う場合には非常に有用です。

ただし、使う場合には以下の注意点があります。

  • GAS側で用意したHTMLファイルをgetContentで引っ張って来れるのは、HTML, CSS。
  • innerHTMLと同じような動きをしますが、ロードしたJavaScriptは別途用意するか?実行できる状態になければならない。
  • ロードしたHTML内でもVueを使えますが、呼び出し元のvueとidが被らないように注意しなければならない。

GAS側コード

  • 単純にHTMLファイルの中身を取得してそのまま返しています。引数はHTML名を取っています。

HTML側コード(moveview.html)

  • ボタンをクリックすると該当するHTMLをGAS側から読みに行き、返り値をv-htmlで指定されている場所へ挿入してくれます。
  • vm_linkの時だけ、makelink関数をHTMLのロード後に実行しています。

HTML側コード(vm_table.html)

  • GAS側からgetContentで取得するHTMLの例です。
  • サンプルのHTMLおよびCSSデータはこちらから利用させていただきました。
  • まるで、vueファイルでパッケージしたかのようなスタイルでGAS側からコードをロードしてそのまま利用する事が可能です。

実行結果

関連リンク

共有してみる: