モミキん更新情報ブログ

パズドラのスキル検索サイト『モミキん』の情報発信ブログ

Vue.jsを使う場合と使わない場合をコードとして見比べる。

前回(3回目)の投稿から2か月も経過してしまったモミジの「スキル、なんだっけ?」の管理人ことかまぼこです。

私生活のことはさておき、前回はモミキん作成を効率的に進めることができたフレームワークVue.jsが従来のjavascriptjQueryとどう異なるか、をアバウトに説明しました。

前回の話の中で、古いjavascriptでは見た目を制御するコードを多数書く必要があり、Vueではそこから脱却できたといいましたので、今日はモミキんの検索IF部分の核部分をサンプルに具体例を示してみようかと思います。

<!-- 見た目部分のコード -->
<div id="app">
    <div v-for="(selected, index) in selects">
        <span @click="Delete(index)">[-]</span>
        <select  v-model="selected.Effect">
            <option v-for="option in Effects" v-bind:value="option.value">
                {{ option.text }}
            </option>
        </select>
    </div>
    <span>
        <input @click="Add" type="button" value="条件追加"/>
    </span>
</div>
<!-- 制御関係のコード -->
<script>
   const app = new Vue({
       el: '#app',
       data: {
               selects:[{}], // 検索条件の効果詳細情報を持つ連想配列の配列
               Effects:[ // 人様用の効果名称とDBに登録してある効果名称の変換用テーブル
                   {text:"未選択", value:null},
                   {text:"変換", value:"変換"},
                   // ...省略
               ],
           },
       methods: {
           Delete(index) {
               // 検索条件からindex番目の要素を取り除く
               this.selects.splice(index, 1); // Vueに配列内の変更を通知するためにこの記法
           },
           Add () {
               // 検索条件を新たに追加する
               this.selects.push({});
           },
       }
   };
</script>

上記のコードは、検索項目を足したり減らしたりするための実際のコードです。 記憶が確かなら、IF部分の出だしはこんなところから始まったはずです。(git管理し始めたのだいぶ後なので詳細なログがない!!)

<div v-for="(selected, index) in selects" >

一番に感動したのはこの部分です。 v-forという属性に xxx in yyyという値を入れることで、Vueのdata要素で定義したyyyという配列の中身をxxxとして展開してくれます。カッコ書きで(selected, index)と書くことで何番目の要素であるかもindexに覚えててくれます。

これで、app.data.selectsにデータを足したり(Add関数)削除する(Delete関数)だけで、検索項目を増減させられます。

次のコードで、selectes配列内の各連想配列にデータをセットする方法ですが、これは以下のようなコードで実装されています。

<select  v-model="selected.Effect">
    <option v-for="option in Effects" v-bind:value="option.value">
        {{ option.text }}
    </option>
</select>

v-model="selected.Effect"と言うのが、select要素のvalueとselected.Effectに紐づけてくれます。 select要素内のoptionリストの生成は先ほどと同様v-forに配列を渡すことでできます。

Vueを使って最も感動をしたのは、v-forやv-bindみたいにHTMLからJavascript内の変数を呼び出したり紐づけたりできることです。 昔のjavascriptjQueryでこれはできませんでした。

もし、最初のコードを古い書き方をすると(あくまでイメージですが)下記のようになると思います。

<div>
    <div id="検索条件">
        <!-- N個目の検索条件の詳細を記述するためのHTMLをここに書けない -->
        <!-- 今、検索条件がいくつあるのかを知っているのはjavascriptだけであり、HTMLはjavascriptが持つ変数を関知しないから -->
    </div>
    <span>
        <input click="Add" type="button" value="条件追加"/>
    </span>
</div>
<script>
   // わずかでも簡略化するため(うろ覚えな)jQuery(的)な書き方で
   let selects = []; // 検索条件の効果詳細情報を持つ連想配列の配列
   let Effects:[ {}, {} ];  // 人様用の効果名称とDBに登録してある効果名称の変換用テーブル
   const form = $("#検索条件");

   fuction WriteSelects() {
       let div = $("<div>");
       for (let i = 0; i < selects.length; i++) {
           let selected = $("<div>");
           selected.append($("<input>", { click:"Delete(" + i + ")", text:"[-]" } ));
           const list = EffectSelectList(i);
           // listの初期選択値をselects[i].Effectとなるようにする処理をここに書く
           selected.append(list);
           div.append(selected);
       }
       form.html(div.html());
   }
   function Add() {
       selects.push({});
       WriteSelects();
   }

   function Delete(index) {
       selects.splice(index, 1);
       WriteSelects();
   }
   function EffecSelectList(index) {
       const id = "Effect" + index;
       const change= "ChangeEffect(" + index + ")";
       let options = $("<select>", {change:change, id: id}); // 選択要素が変わったときにJavascriptに通知するように変更時呼び出される関数を(この要素だと特定できる引数と合わせて)定義する
       for (let i = 0; i < Effects.length; i++) {
           options.append($("<option>", {value:Effects[i].value, text:Effects[i].text}));
       }
   }
   function ChangeEffect (index) {
       selects[index].Effect = $("#Effect" + index).value;
   }
</script>

ざっくりVue.jsではJS部分が20~25行程度、古い書き方では(関数を一部省略してなお)35~40行程度となりました。 古い書き方の一番面倒なところは、WriteSelectsとEffecSelectListのようにHTMLを記述するJavascriptがあるところです。さらにこの構造を複雑にする要因に、JavascriptでHTMLを書き、そのHTMLからJavascriptを呼び出すための属性を付与していることも挙げられます。

古いJavascriptとVue.jsのコードを比べると、共通のロジックはAdd()とDelete()と配列宣言部だけであることと、Vue.jsではVue関連の宣言を除くと共通部しかないことがわかります。

一方、Vue.js側のHTML部分は15行程度、古いJavascriptでは7行程度とHTMLは古い書き方の方が一見短くシンプルに見えます。 しかし前回の記事でも説明したように古い書き方ではJavascript内にHTMLを記述するコードが多くなり、今回で言えばそれは(35 - 20 = )15行程度あることが分かります。

コードの総量的な意味でもVue.jsに軍配が上がりますがそれ以上に、見た目的な話をJavascript内に持ち込まざるを得ない古い書き方ではHTMLを見てもどんなサイトなのか想像することができません。

仮想DOMも考えると描画速度のメリットもVue.jsにはあるような気はしますが、直接比較したことないのでそんな気がするよ程度で。

最後に、Vue.jsの良い点を再三になる部分もありますがまとめますと、

  • Javascript内にHTMLを書かなくて済む
  • 上記のおかげで、Javascriptを呼ぶHTMLをJavascriptで書く、ということがなくなる
  • 見た目の記述はすべてHTMLやCSS、利用データ部分はdata部、ロジック部はmethodos、computed部に切り分けられる
  • 複雑な構造になるほど記述量が古い書き方より少なく済む
  • 描画速度が多分速い

なんてことが言えるかなと思います。 こんな良いところ(悪いところでも)があるよ! という話があればぜひ教えてください。

ではでは~。